Pie*_*nry 15
我经常看到框架或库引发的异常,例如Hibernate或Spring引用本身作为原因(在过程中混淆了调试器GUI).
我总是想知道为什么他们这样做,因为它似乎是个坏主意.今天,当我尝试将一个序列化为JSON时,它实际上引起了一个问题:bam,enless cycle.
所以我进一步调查了一下:
在Throwable这里列出的所有源代码(来自JDK 1.7)的源代码中我们有:
/**
* The throwable that caused this throwable to get thrown, or null if this
* throwable was not caused by another throwable, or if the causative
* throwable is unknown. If this field is equal to this throwable itself,
* it indicates that the cause of this throwable has not yet been
* initialized.
*
* @serial
* @since 1.4
*/
private Throwable cause = this;
Run Code Online (Sandbox Code Playgroud)
现在我特意遇到了一个扩展的异常类的问题RuntimeException,所以我从那里开始.其中一个构造函数RuntimeException:
/** Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public RuntimeException(String message) {
super(message);
}
Run Code Online (Sandbox Code Playgroud)
Exception由上面调用的构造函数:
/**
* Constructs a new exception with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Exception(String message) {
super(message);
}
Run Code Online (Sandbox Code Playgroud)
Throwable由上面调用的构造函数:
/**
* Constructs a new throwable with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* <p>The {@link #fillInStackTrace()} method is called to initialize
* the stack trace data in the newly created throwable.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
Run Code Online (Sandbox Code Playgroud)
fillInStackTrace 是一个本机方法,似乎没有修改原因字段.
正如您所看到的,除非initCause随后调用该方法,否则该cause字段永远不会从原始值更改this.
结论:如果您Exception使用不带cause参数的构造函数创建一个新的(或者在野外存在的许多子类中的一个并且不覆盖此行为),并且您不调用该initCause方法,那么原因是例外将是它自己!
所以我想这应该是一个非常常见的事情.
小智 11
接受的答案是误导性的,其他答案是不完整的.所以...
虽然将异常作为其自身原因传递将是不好的设计,但在Throwable实现中出于这个原因是不可能的.原因是在构造期间传入,或者传递给initCause()方法,并且如第二个答案所指出的,后者将导致IllegalArgumentException.
作为第三个答案指出,如果你不提供一个原因,原因将是这个按照该实施的Throwable.
可能缺少的(给出原始问题)是Throwable的getCause()方法永远不会返回它,如果cause == this,它返回null.因此,尽管您的调试器将此引用显示为原因,因为它使用反射,但在使用Throwable的公共接口时,您将看不到它,因此它不会成为问题.
不,那只是糟糕的设计。如果异常是根本原因,则不需要定义原因。
有原因的异常是不同异常包装的合法情况。例如,如果创建持久性存储,您可能想要抛出 PersistenceExcpetion。因此,如果它是文件存储,则原因可能是 IOException。如果是数据库,可能原因是 SqlException。ETC
| 归档时间: |
|
| 查看次数: |
2693 次 |
| 最近记录: |