简体   繁体   English

什么时候InvocationTargetException.getCause()null?

[英]When is InvocationTargetException.getCause() null?

As per the javadocs , InvocationTargetException.getCause() can be null: 根据javadocsInvocationTargetException.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被改装时,我认为语言设计者想要:

  1. prevent the possibility of InvocationTargetException having two different "causes" - one stored in target and the other in cause ; 防止InvocationTargetException有两个不同的“原因” - 一个存储在target ,另一个存储在cause ; and still 还是
  2. be backward-compatible with existing code that relies on the 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. 当然, InvocationTargetExceptiongetCause()实现会返回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指定nullprotected默认构造函数,从而允许继承类来构造所需的类。

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 targetcause 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 . 如果方法抛出异常,它将存储在InvocationTargetExceptiontarget字段中。 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值为nullpublic构造函数。 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.

相关问题 尝试查找异常源时,Exception.getCause() 返回 null - Exception.getCause() returning null when trying to find the source of an exception 可抛出的 getCause 返回 null - Throwable getCause returns null 如何修复FileReader错误,其中在读取csv文件时getCause指向null? - How to fix FileReader error where getCause points to null when reading csv file? java.lang.exception.getCause() 每次都为 null - java.lang.exception.getCause() gets null every time 使用JavaFX时InvocationTargetException - InvocationTargetException when using JavaFX 发生InvocationTargetException:Play框架中为null - InvocationTargetException occured : null in Play framework 执行异常InvocationTargetException:使用Play Framework Java在Linux / OSX环境中执行测试时为null - Execution exception InvocationTargetException: null when executing the tests in Linux/OSX environment using Play Framework Java java.lang.reflect.InvocationTargetException:null - java.lang.reflect.InvocationTargetException: null 在junit中运行方法时InvocationTargetException - InvocationTargetException when running a method in junit 运行 javafx 程序时的 InvocationTargetException - InvocationTargetException when running a javafx program
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM