好吧,基本上,throw e 将 “重新抛出”(传递)所有原始值(因为相同的 Exception 实例,将使用相同的对象)- 这将导致,它会还传递一些代码流-可能应该隐藏,例如出于安全原因。
如果您将重新创建异常,您将获得 - 或者更好地说“您可以获得” - 使用 new Exception instance 在该位置的另一个堆栈跟踪。
因此,我想说,在这种情况下,您可以选择屏蔽某些数据(例如,您会将异常记录到特殊日志中,但您希望将其他诊断数据传递给最终用户)。
让我们来看看下面的细节:
- 我创建了一个类作为唯一的简单异常生成器
- 另一个类允许重新抛出或重新创建异常
- 之后,我只是打印堆栈跟踪并比较结果
异常生成器
public class ExceptionsThrow {
public static void throwNewException() throws Exception {
throw new Exception("originally thrown message");
}
}
重新抛出/重新创建异常的类
public class Exceptions {
public static void reThrowException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
//re-throw existing exception
throw e;
}
}
public static void reCreateNewException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
//recreation of the exception > new instance is thrown
throw new Exception(e);
}
}
}
测试代码示例:
try {
Exceptions.reThrowException();
} catch (Exception e) {
System.out.println("1st RETHROW");
e.printStackTrace();
System.out.println("===========");
}
try {
Exceptions.reCreateNewException();
} catch (Exception e) {
System.out.println("2nd RECREATE");
e.printStackTrace();
System.out.println("===========");
}
最后是输出:
1st RETHROW
java.lang.Exception: originally thrown message
at test.main.stackoverflow.ExceptionsThrow.throwNewException(ExceptionsThrow.java:5)
at test.main.stackoverflow.Exceptions.reThrowException(Exceptions.java:7)
at test.main.MainTest.main(MainTest.java:110)
java.lang.Exception: java.lang.Exception: originally thrown message===========
2nd RECREATE
at test.main.stackoverflow.Exceptions.reCreateNewException(Exceptions.java:17)
at test.main.MainTest.main(MainTest.java:118)
Caused by: java.lang.Exception: originally thrown message
at test.main.stackoverflow.ExceptionsThrow.throwNewException(ExceptionsThrow.java:5)
at test.main.stackoverflow.Exceptions.reCreateNewException(Exceptions.java:15)
... 1 more
===========
在这种情况下,您可以看到大部分相同的数据,但也可以看到一些额外的数据,您可以看到原始消息,因为我使用相同的异常来构建新的 - 但没有必要像这样创建新的异常实例,那么你可以掩盖原来的原因,或者你不需要暴露应用程序的逻辑,例如让我们再看一个例子:
- 我将仅从原始异常中获取原因,但它会覆盖数据
- 如您所见,新创建的异常不包含完整的堆栈跟踪,作为来源
所以:
public static void maskException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
throw new Exception("I will dont tell you",e.getCause());
}
}
结果:
===========
3rd mask
java.lang.Exception: I will don't tell you
at test.main.stackoverflow.Exceptions.maskException(Exceptions.java:25)
at test.main.MainTest.main(MainTest.java:126)
===========
所以,我想说,用同一个实例重新创建异常有点没有意义,但是一旦需要异常转换(重新键入另一个异常类型(那么实际上你应该也可以使用java cast),或者你想要掩码数据
在现实世界中,我记得很常见的问题,当某些门户网站仅通过打印这种情况来处理 PHP 脚本中的异常时,通常,当与数据库的连接无法正常工作时,连接字符串例如,(包括明文形式的数据库地址和凭据)在 Web 浏览器中可见。 :)