As per the javadocs, InvocationTargetException.getCause()
can be null:
Returns the cause of this exception (the thrown target exception, which may be 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.
So it seems to me that InvocationTargetException.getCause()
can never be null
.
Am I missing something?
UPDATE
Yes, I missed something -- the default constructor of InvocationTargetException
would cause getCause()
to be 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?
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.
My guess is that the text for getCause() that states "which may be null" is just boilerplate copied from the Throwable.getCause() Javadoc.
First, its worth mentioning that not only
null
cause is permitted via theprotected
constructor. You can also invoke thepublic
construcors withtarget
valued tonull
. NoNullPointerException
will occur...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:
That way, util method can create
InvocationTargetException
instances and pass them to client code that adds up the particular cause.So.
@xtravar's comment on my (much) earlier answer has caused be to have another look at this issue. And I might just got it. Please bear with me.
InvocationTargetException
was introduced to Java very early. At least as early as some JDK 1.1.X which dates back to anywhere between February 1997 to December 1998. How do I know it's that old? After all, there's no@since 1.1
mark on the class.I happened to see the following javadoc on the
serialVersionUID
field:Right. So what?
So, according to docs of
Throwable.getCause()
, whichInvocationTargetException
eventually inherits:Now, please combine this with the following note on
InvocationTargetException
class docs:See where I'm getting at?
The note on
Throwable.getCause()
is aimed exactly atInvocationTargetException
(for the least).InvocationTargetExcpetion
was used to chain exceptions before exception-chaining was introduced toThrowable
...And when
InvocationTargetException
was retrofitted, as noted, I assume that the language designers wanted to:InvocationTargetException
having two different "causes" - one stored intarget
and the other incause
; and stilltarget
field.That's why they left the
target
field as the one that's really used and implemented any existing constructors so that thecause
field remainsnull
for good. The implementation ofgetCause()
forInvocationTargetException
, of course, returnstarget
as the cause.So to answer
Not really, it's not how the class is - and was - intended to be used.
And yet, this question remains:
(and this constructor seems to exist ever since)
I tend to think that this class is actually quite
null
-tolerant. After all, thepublic
constructors permitnull
as theThrowable target
. As a designer, if you already permitted that, you may as well add theprotected
default constructor that explicitly assignsnull
totarget
, enabling inheriting classes to construct the class however needed.This also answers the original question:
Yes.
InvocationTargetException
is indeed intended to have a non-null
target
andcause
. However, what's "missed" here is thattarget
(and hencecause
) unfortunately can benull
, as nothing in the class forces it otherwise.InvocationTargetException
extendsReflectiveOperationException
which statesWhen you use reflection to call a method (or constructor).
If the method threw an exception, it would be stored in the
target
field ofInvocationTargetException
. 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