什么时候InvocationTargetException.getCause()null?
根据javadocs , InvocationTargetException.getCause()
可以为null:
返回此exception的原因(抛出的目标exception,可能为null)。
但文档还说它包装了一个现有的exception:
InvocationTargetException是一个已检查的exception,它包装被调用的方法或构造函数抛出的exception。
所以在我看来, InvocationTargetException.getCause()
永远不能为null
。
我错过了什么吗?
UPDATE
是的,我错过了一些东西 – InvocationTargetException
的默认构造函数会导致getCause()
为null。
我现在的问题是为什么要提供这个类的默认构造函数。 是否存在需要使用null原因抛出exception的用例?
InvocationTargetException
扩展了InvocationTargetException
ReflectiveOperationException
核心reflection中reflection操作抛出的常见超类exception。
使用reflection调用方法(或构造函数)时。
Method method = ... method.invoke(instance, ...);
如果方法抛出exception,它将存储在InvocationTargetException
的target
字段中。 在大多数反思案例中都会发生这种情况。
有一个空构造函数的事实让我相信它可能在其他情况下使用不同。
JDK 7
private Throwable target; /** * Constructs an {@code InvocationTargetException} with * {@code null} as the target exception. */ protected InvocationTargetException() { super((Throwable)null); // Disallow initCause }
所以。
@ xtravar对我(很多)早期答案的评论导致我们再看看这个问题。 我可能刚刚得到它。 请多多包涵。
InvocationTargetException
很早就被引入了Java。 至少早在1997年2月到1998年12月之间的一些JDK 1.1.X。 我怎么知道那是旧的? 毕竟, @since 1.1
上没有@since 1.1
分。
我碰巧在serialVersionUID
字段上看到以下javadoc:
/** * Use serialVersionUID from JDK 1.1.X for interoperability */
对。 所以呢?
因此,根据Throwable.getCause()
文档, InvocationTargetException
最终会inheritance:
While it is typically unnecessary to override this method, a subclass can override it to return a cause set by some other means. This is appropriate for a "legacy chained throwable" that predates the addition of chained exceptions to Throwable. ... @since 1.4
现在,请将此与InvocationTargetException
类docs的以下注释结合起来:
As of release 1.4, this exception has been retrofitted to conform to the general purpose exception-chaining mechanism. The "target exception" that is provided at construction time and accessed via the getTargetException() method is now known as the cause, and may be accessed via the Throwable.getCause() method, as well as the aforementioned "legacy method."
看看我在哪里?
关于Throwable.getCause()
的注释完全针对InvocationTargetException
(为最少)。 在将exception链引入Throwable
之前, InvocationTargetExcpetion
用于链接exception…
如上所述,当InvocationTargetException
被改装时,我认为语言设计者想要:
- 防止
InvocationTargetException
有两个不同的“原因” – 一个存储在target
,另一个存储在cause
; 还是 - 与依赖于
target
字段的现有代码向后兼容。
这就是为什么他们将target
字段保留为真正使用并实现任何现有构造函数的target
字段,以便cause
字段保持为null
。 当然, InvocationTargetException
的getCause()
实现会返回target
作为原因。
所以回答
是否存在需要使用null原因抛出exception的用例?
不是真的,并不是这个课程的用途 – 而且是 – 有意使用。
然而,这个问题仍然存在:
为什么要提供这个类的默认构造函数
( 此后这个构造函数似乎存在 )
我倾向于认为这个类实际上是非常容忍的。 毕竟, public
构造函数允许null
作为Throwable target
。 作为设计者,如果您已经允许,那么您也可以添加显式为target
指定null
的protected
默认构造函数,从而允许inheritance类来构造所需的类。
这也回答了原来的问题:
所以在我看来,InvocationTargetException.getCause()永远不能为null。
我错过了什么吗?
是。 InvocationTargetException
确实旨在具有非null
target
和cause
。 然而,这里“遗漏”的是,遗憾的是, target
(以及因此cause
) 可以为null
,因为类中的任何东西都不会强制它。
我同意你的观点 – 我不知道InvocationTargetException如何可以为null,因为它仅在目标抛出exception时抛出。
我的猜测是getCause()的文本声明“可能为null”只是从Throwable.getCause()Javadoc复制的样板文件。
首先,值得一提的是,通过protected
构造函数不仅允许null
原因。 您还可以调用target
值为null
的public
构造函数。 不会发生NullPointerException
…
话虽如此,它确实看起来不仅仅是设计师刚刚滑倒的东西。
可能是设计者想要通过reflection实现类的实例化,如:
Constructor ctor = // ... some code to get the no-arg constructor that I spared here ctor.setAccessible(true); // it's protected constructor... InvocationTargetException e = (InvocationTargetException) ctor.newInstance();
这样,util方法可以创建InvocationTargetException
实例并将它们传递给客户端代码,从而将特定原因相加。