throw e和throw new Exception(e)有什么区别?

Vin*_*yak 38 java exception try-catch throw

考虑:

try  {
    // Some code here
} catch (IOException e) {
    throw e;
} catch (Exception e) {
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

throw e和之间有什么区别throw new Exception(e)

try  {
   // Some code here
} catch (IOException e) {
   throw new IOException(e);
} catch (Exception e) {
   throw new Exception(e);
}
Run Code Online (Sandbox Code Playgroud)

And*_*lko 47

如果您不需要调整异常类型,则无需更改即可重新抛出(进一步抛出)相同的实例

catch (IOException e) {
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

如果确实需要调整异常类型,则将(原因)包装e为所需类型的新异常

catch (IOException e) {
    throw new IllegalArgumentException(e);
}
Run Code Online (Sandbox Code Playgroud)

我认为所有其他情况都有代码气味。您的第二个片段就是一个很好的例子。


以下是可能弹出的问题的答案。

我为什么要抛出异常?

你可以放手 但是,如果发生这种情况,您将无法在此级别上执行任何操作。

当我们在方法中捕获异常时,我们仍在该方法中并可以访问其范围(例如,局部变量及其状态)。在抛出异常之前,我们可以做任何需要做的事情(例如,记录一条消息,将其发送到某个地方,对当前状态进行快照)。

我为什么要调整例外?

根据经验,

较高的层应捕获较低级别的异常,并代之以抛出可以根据较高层抽象进行解释的异常。

有效的Java-第2版-项目61:抛出适合于抽象的异常

换句话说,从某种意义上说,一种晦涩IOException的事物应该转变为一种明显的事物MySpecificBusinessRuleException

我称其为“调整异常类型”,聪明的人将其称为异常转换(尤其是异常链接)。


为了清楚起见,让我们举一些愚蠢的例子。

class StupidExample1 {
    public static void main(String[] args) throws IOException {
        try {
            throw new IOException();
        } catch (IOException e) {
            throw new IOException(new IOException(e));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

导致像这样的详细堆栈跟踪

Exception in thread "main" java.io.IOException: java.io.IOException: java.io.IOException
    at StupidExample1.main(XXX.java:XX)
Caused by: java.io.IOException: java.io.IOException
    ... 1 more
Caused by: java.io.IOException
    at StupidExample1.main(XXX.java:XX)
Run Code Online (Sandbox Code Playgroud)

可以(并且应该)有效地减少到

Exception in thread "main" java.io.IOException
    at StupidExample1.main(XXX.java:XX)
Run Code Online (Sandbox Code Playgroud)

另一个:

class StupidExample2 {
    public static void main(String[] args) {
        takeString(new String(new String("myString")));
    }

    static void takeString(String s) { }
}
Run Code Online (Sandbox Code Playgroud)

显然,这new String(new String("myString"))是一个罗word的版本,"myString"应重构为后者。


Ant*_*sss 14

catch (IOException e) {
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

您将看到仅具有原始stacktrace的原始异常。您不会在堆栈跟踪中看到此“重新抛出”行,因此它是透明的。

catch (IOException e) {
    throw new IllegalStateException(e);
}
Run Code Online (Sandbox Code Playgroud)

您将看到created IllegalStateException和它的堆栈跟踪以及原始异常信息和堆栈跟踪的“原因”。您正在(即将)将抛出的异常设置为新创建的的原因IOException。上层将看到IllegalStateException并且可以捕获(您不会捕获该捕获原因异常)。

catch (IOException e) {
     throw new IOException();
}
Run Code Online (Sandbox Code Playgroud)

您将仅看到IOException创建的当前堆栈跟踪,没有添加原因。