为什么我们总是要抛出新的异常?我们可以不将该异常存储为实例变量并每次都抛出相同的实例吗?

Aru*_*wda 4 java error-handling exception

在java中,到目前为止我看到的是,每当我们抛出异常时,我们都会抛出新的异常。像下面的例子。

try{
    somethingThatCanGoWrong();
}catch(Exception e){
    throw new FailedToDoSomethingException("The other guy failed");
}
Run Code Online (Sandbox Code Playgroud)

是否总是需要抛出一个新的异常实例?我可以通过以下方式做到吗?

public class Blah
{
    private static final FailedToDoSomethingException failedToDoSomethingException = new FailedToDoSomethingException(
        "The other guy failed" );

    public static void main( String[] args )
    {
        try {
            somethingThatCanGoWrong();
        } catch ( Exception e ) {
            throw failedToDoSomethingException;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由于两个原因,我不喜欢最后一个例子。

  1. 面向对象,任何 Exception 既不是 Class 的属性,也不是实例的属性。
  2. 当异常消息是动态生成的并且基于方法参数时,在多线程环境中会失败。以下是示例。

    File getFile(String filePath){

    throw new FileNotFoundException("File at path: "+filePath+" was not found");

    }

除了以上2个原因,还有其他原因吗?当我们创建异常的新实例时,幕后有什么事情发生吗?类似于填充异常上下文(如堆栈跟踪。但我相信当我们使用throw关键字时会发生这种情况)?

或者一直抛出一个新的异常只是一个好习惯?(再次,为什么这是一个好习惯?)

Pet*_*tig 6

堆栈跟踪显示异常创建时的行,因此您无法真正看到它被抛出的位置。

你可以执行这个例子:

public class Foo {

    private static final RuntimeException re = new RuntimeException("MSG");

    public static void main(String[] args) {
        try {
            Integer.parseInt("!!#!");
        } catch (Exception e) {
            throw re;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当您查看堆栈跟踪时:

Exception in thread "main" java.lang.RuntimeException: MSG
    at test.Foo.<clinit>(Foo.java:5)
Run Code Online (Sandbox Code Playgroud)

您会看到堆栈跟踪中的行不是您实际抛出异常的行,而是您调用的行 new