基本上,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) {
throw e;
}
}
public static void reCreateNewException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
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强制转换),或者您想要屏蔽数据)。
在现实世界中,我记得真正经常出现的问题是,一些Web门户仅通过打印这种方式处理PHP脚本中的异常。通常当与数据库的连接无法正常工作时,例如,连接字符串(包括纯文本中的数据库地址和凭据)可见于Web浏览器中。 :)
throw
后面跟着一个表达式,该表达式解析为一个Throwable
对象。e
是一个Throwable
对象表达式,new Exception(e)
也是一个Throwable
对象表达式,两者的区别只在于创建 throwable 对象的方式。e
是由catch
块提供的,而new Exception(e)
则是由你的代码创建的。 - ernest_k