java 在java中重新抛出异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11972765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:07:33  来源:igfitidea点击:

Rethrow exception in java

javaexceptionexception-handling

提问by MinhHoang

I have a very simple question about re-throwing exception in Java.

我有一个关于在 Java 中重新抛出异常的非常简单的问题。

Here is the code snippet:

这是代码片段:

public static void main(String[] args) throws FileNotFoundException {
    try {
        FileReader reader = new FileReader("java.pdf");
    } catch (FileNotFoundException ex) {
        throw ex;
    }
}

public static void main(String[] args) throws FileNotFoundException {        
        FileReader reader = new FileReader("java.pdf");        
}

Why do we need to re-throw exin the first version while the second version looks more elegant? What might be the benefits and which version is preferred over the other?

为什么我们需要ex在第一个版本中重新抛出而第二个版本看起来更优雅?可能有什么好处,哪个版本比另一个更受欢迎?

回答by AlexR

You are right. Second version is better. Moreover the first version does not make any sense. It does the same except the stack trace of the exception will be "wrong".

你说的对。第二个版本更好。此外,第一个版本没有任何意义。除了异常的堆栈跟踪将是“错误的”之外,它的作用相同。

There are the following reasons to "re-throw" exceptions:

“重新抛出”异常有以下原因:

  1. If you have something to do before.
  2. If you catch exception of one type and throw exception of other type:
  1. 如果之前有事。
  2. 如果您捕获一种类型的异常并抛出另一种类型的异常:

example:

例子:

try {
   // do something
} catch (IOException ioe) {
    throw new IllegalStateException(ioe);
}

回答by pb2q

In the example given, re-throwing the Exceptionserves no purpose.

在给出的示例中,重新抛出Exception没有任何意义。

Doing this canbe useful if the method that catches and then re-throws the exception needs to take some additional action upon seeing the Exception, and also desires that the Exceptionis propagated to the caller, so that the caller can see the Exceptionand also take some action.

这样做可以,如果方法捕获,然后重新抛出异常的需求见状将采取一些额外措施是有用的Exception,并且还期望在Exception被传播给调用者,这样调用者可以看到Exception,并采取一些行动.

回答by smcg

I would only catch/rethrow an exception (instead of just throwing it) if I wanted to do something else in the catch block - for example, write a logging statement before rethrowing.

如果我想在 catch 块中做其他事情,我只会捕获/重新抛出一个异常(而不是仅仅抛出它)——例如,在重新抛出之前写一个日志语句。

回答by jcern

In addition to wanting to do something with the exception before exiting - like logging, the other time you would do something like that is if you want to wrap it as a different exception, like:

除了想在退出之前对异常做一些事情——比如日志记录,另外一次你会做类似的事情,如果你想把它包装成一个不同的异常,比如:

try {
    FileReader reader = new FileReader("java.pdf");
} catch (FileNotFoundException ex) {
    throw new ServletException(ex);
}

回答by Marko Topolnik

The question is why you think you need to rethrow the exception. Did Eclipse suggest surrounding with try-catch? In practice we rarely rethrow the same exception, but very often catch one and throw another that wrapsthe first one, especially if the wrapper exception is unchecked. This happens whenever you have calls declaring checked exceptions, but the method you write those calls in doesn't declare those exceptions:

问题是为什么您认为需要重新抛出异常。Eclipse 是否建议使用try-catch? 在实践中,我们很少重新抛出相同的异常,但经常捕获一个并抛出另一个包装第一个异常的异常,特别是如果包装器异常未被检查。每当您有调用声明已检查的异常时就会发生这种情况,但是您编写这些调用的方法没有声明这些异常:

public int findId(String name) {
  try {
    return db.select("select id from person where name=?", name);
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }
}

回答by Julien

Both versions will output the same stacktrace

两个版本都将输出相同的堆栈跟踪

without try/catch

没有尝试/捕获

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
//        try {
            FileReader reader = new FileReader("java.pdf");
//        } catch (FileNotFoundException ex) {
//            throw ex;
//        }
    }
}

will output

会输出

Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)

with try/catch/throw same exception

与 try/catch/throw 相同的异常

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        try {
            FileReader reader = new FileReader("java.pdf");
        } catch (FileNotFoundException ex) {
            throw ex;
        }
    }
}

will output exactly the same as before

将输出与以前完全相同

Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)

try/catch/throw wrapping exception

尝试/捕获/抛出包装异常

An advisable approach is to throw your own exceptions. wrap the exception you just caught into it if you want to provide details of the root cause (might be wanted or not wanted)

一个可取的方法是抛出您自己的异常。如果您想提供根本原因的详细信息(可能需要或不需要),请包装您刚刚捕获的异常

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("java.pdf");
        } catch (FileNotFoundException ex) {
            throw new RuntimeException("Error while doing my process", ex);
        }
    }
}

You can clearly see the top-level issue (my process did not complete), and the root cause that led to it (java.pdf file not found)

您可以清楚地看到顶级问题(我的流程没有完成),以及导致它的根本原因(找不到 java.pdf 文件)

Exception in thread "main" java.lang.RuntimeException: Error while doing my process
    at Test.main(Test.java:9)
Caused by: java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)

回答by Pankti

The flow of execution stops immediately after the throwstatement; any subsequent statements are not executed. The nearest enclosing tryblock is inspected to see if it has a catchstatement that matches the type of exception.

执行流程在throw语句之后立即停止;不执行任何后续语句。try检查最近的封闭块以查看它是否具有catch与异常类型匹配的语句。

If it does find a match, control is transferred to that statement. If not, then the next enclosing trystatement is inspected and so on. If no matching catchis found, then the default exception handler halts the program and prints the stack trace.

如果确实找到匹配项,则将控制权转移到该语句。如果不是,则try检查下一个封闭语句,依此类推。如果未catch找到匹配项,则默认异常处理程序将停止程序并打印堆栈跟踪。

If the method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception.

如果该方法能够导致它无法处理的异常,则它必须指定此行为,以便该方法的调用者可以保护自己免受该异常的影响。

One can do this by including a throwsclause in method's declaration. A throwsclause lists the types of exceptions that a method might throw. This is necessary for all exceptions, except those of type Erroror RuntimeException, or any of their subclasses. All other exceptions that a method can throw must be declared int the throwsclause. If they are not, a compile-time error will result.

可以通过throws在方法声明中包含一个子句来做到这一点。一throws条款列出了异常类型的一个方法可能抛出。这对于所有异常都是必需的,除了类型ErrororRuntimeException或其任何子类的异常。方法可以抛出的所有其他异常必须在throws子句中声明。如果不是,则会导致编译时错误。