[英]When is InvocationTargetException.getCause() null?
As per the javadocs , InvocationTargetException.getCause()
can be null: 根据javadocs ,
InvocationTargetException.getCause()
可以为null:
Returns the cause of this exception (the thrown target exception, which may be null).
返回此异常的原因(抛出的目标异常,可能为null)。
But the documentation also says that it wraps an existing exception: 但文档还说它包装了一个现有的异常:
InvocationTargetException is a checked exception that wraps an exception thrown by an invoked method or constructor.
InvocationTargetException是一个已检查的异常,它包装被调用的方法或构造函数抛出的异常。
So it seems to me that InvocationTargetException.getCause()
can never be null
. 所以在我看来,
InvocationTargetException.getCause()
永远不能为null
。
Am I missing something? 我错过了什么吗?
UPDATE UPDATE
Yes, I missed something -- the default constructor of InvocationTargetException
would cause getCause()
to be null. 是的,我错过了一些东西 -
InvocationTargetException
的默认构造函数会导致getCause()
为null。
The question I have now is why provide a default constructor for this class at all. 我现在的问题是为什么要提供这个类的默认构造函数。 Is there a usecase where the exception needs to be thrown with a null cause?
是否存在需要使用null原因抛出异常的用例?
So. 所以。
@xtravar's comment on my (much) earlier answer has caused be to have another look at this issue. @ xtravar对我(早)回答的评论引起了对这个问题的再看。 And I might just got it.
我可能刚刚得到它。 Please bear with me.
请多多包涵。
InvocationTargetException
was introduced to Java very early. InvocationTargetException
很早就被引入了Java。 At least as early as some JDK 1.1.X which dates back to anywhere between February 1997 to December 1998 . 至少早在1997年2月到1998年12月之间的一些JDK 1.1.X。 How do I know it's that old?
我怎么知道它那么老? After all, there's no
@since 1.1
mark on the class. 毕竟,
@since 1.1
上没有@since 1.1
分。
I happened to see the following javadoc on the serialVersionUID
field: 我碰巧在
serialVersionUID
字段上看到以下javadoc:
/**
* Use serialVersionUID from JDK 1.1.X for interoperability
*/
Right. 对。 So what?
所以呢?
So, according to docs of Throwable.getCause()
, which InvocationTargetException
eventually inherits: 因此,根据
Throwable.getCause()
文档, InvocationTargetException
最终会继承:
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
Now, please combine this with the following note on InvocationTargetException
class docs: 现在,请将此与
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."
See where I'm getting at? 看看我在哪里?
The note on Throwable.getCause()
is aimed exactly at InvocationTargetException
(for the least). 关于
Throwable.getCause()
的注释完全针对InvocationTargetException
(最少)。 InvocationTargetExcpetion
was used to chain exceptions before exception-chaining was introduced to Throwable
... 在将异常链引入
Throwable
之前, InvocationTargetExcpetion
用于链接异常...
And when InvocationTargetException
was retrofitted, as noted, I assume that the language designers wanted to: 如上所述,当
InvocationTargetException
被改装时,我认为语言设计者想要:
InvocationTargetException
having two different "causes" - one stored in target
and the other in cause
; InvocationTargetException
有两个不同的“原因” - 一个存储在target
,另一个存储在cause
; and still target
field. target
字段的现有代码向后兼容。 That's why they left the target
field as the one that's really used and implemented any existing constructors so that the cause
field remains null
for good. 这就是为什么他们将
target
字段保留为真正使用并实现任何现有构造函数的target
字段,以便cause
字段保持为null
。 The implementation of getCause()
for InvocationTargetException
, of course, returns target
as the cause. 当然,
InvocationTargetException
的getCause()
实现会返回target
作为原因。
So to answer 所以回答
Is there a usecase where the exception needs to be thrown with a null cause?
是否存在需要使用null原因抛出异常的用例?
Not really, it's not how the class is - and was - intended to be used. 不是真的,不是这个课程的用途 - 而且是 - 打算使用。
And yet, this question remains: 然而,这个问题仍然存在:
why provide a default constructor for this class at all
为什么要提供这个类的默认构造函数
(and this constructor seems to exist ever since ) ( 此后这个构造函数似乎存在 )
I tend to think that this class is actually quite null
-tolerant. 我倾向于认为,这一类其实是相当
null
-tolerant。 After all, the public
constructors permit null
as the Throwable target
. 毕竟,
public
构造函数允许null
作为Throwable target
。 As a designer, if you already permitted that, you may as well add the protected
default constructor that explicitly assigns null
to target
, enabling inheriting classes to construct the class however needed. 作为设计者,如果您已经允许,那么您也可以添加显式为
target
指定null
的protected
默认构造函数,从而允许继承类来构造所需的类。
This also answers the original question: 这也回答了原来的问题:
So it seems to me that InvocationTargetException.getCause() can never be null.
所以在我看来,InvocationTargetException.getCause()永远不能为null。
Am I missing something?
我错过了什么吗?
Yes. 是。
InvocationTargetException
is indeed intended to have a non- null
target
and cause
. InvocationTargetException
确实是有意具有非null
target
和cause
。 However, what's "missed" here is that target
(and hence cause
) unfortunately can be null
, as nothing in the class forces it otherwise. 然而,这里“错过”的是,遗憾的是,
target
(以及因此cause
) 可以为null
,因为类中的任何东西都不会强制它。
InvocationTargetException
extends ReflectiveOperationException
which states InvocationTargetException
扩展了InvocationTargetException
ReflectiveOperationException
Common superclass of exceptions thrown by reflective operations in core reflection.
核心反射中反射操作抛出的常见超类异常。
When you use reflection to call a method (or constructor). 当您使用反射来调用方法(或构造函数)时。
Method method = ...
method.invoke(instance, ...);
If the method threw an exception, it would be stored in the target
field of InvocationTargetException
. 如果方法抛出异常,它将存储在
InvocationTargetException
的target
字段中。 That'll happen in most reflection cases. 在大多数反思案例中都会发生这种情况。
The fact that there is an empty constructor leads me to believe it might be used differently in other cases. 有一个空构造函数的事实让我相信它可能在其他情况下使用不同。
JDK 7 JDK 7
private Throwable target;
/**
* Constructs an {@code InvocationTargetException} with
* {@code null} as the target exception.
*/
protected InvocationTargetException() {
super((Throwable)null); // Disallow initCause
}
I agree with you -- I don't see how InvocationTargetException can ever be null, because it's only thrown when the target throws an exception. 我同意你的观点 - 我不知道InvocationTargetException如何可以为null,因为它仅在目标抛出异常时抛出。
My guess is that the text for getCause() that states "which may be null" is just boilerplate copied from the Throwable.getCause() Javadoc. 我的猜测是getCause()的文本声明“可能为null”只是从Throwable.getCause()Javadoc复制的样板文件。
First, its worth mentioning that not only null
cause is permitted via the protected
constructor. 首先,值得一提的是,通过
protected
构造函数不仅允许null
原因。 You can also invoke the public
construcors with target
valued to null
. 您还可以调用
target
值为null
的public
构造函数。 No NullPointerException
will occur... 不会发生
NullPointerException
...
Having said that, it does seem like more than something that the designers just slipped. 话虽如此, 它似乎是比一些设计师只是滑倒了。
Could be that the designers wanted to enable instantiating the class via reflection, as in: 可能是设计者想要通过反射实现类的实例化,如:
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();
That way, util method can create InvocationTargetException
instances and pass them to client code that adds up the particular cause. 这样,util方法可以创建
InvocationTargetException
实例并将它们传递给客户端代码,从而将特定原因相加。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.