簡體   English   中英

什么時候InvocationTargetException.getCause()null?

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

根據javadocsInvocationTargetException.getCause()可以為null:

返回此異常的原因(拋出的目標異常,可能為null)。

但文檔還說它包裝了一個現有的異常:

InvocationTargetException是一個已檢查的異常,它包裝被調用的方法或構造函數拋出的異常。

所以在我看來, InvocationTargetException.getCause() 永遠不能為null

我錯過了什么嗎?

UPDATE

是的,我錯過了一些東西 - InvocationTargetException的默認構造函數會導致getCause()為null。

我現在的問題是為什么要提供這個類的默認構造函數。 是否存在需要使用null原因拋出異常的用例?

所以。

@ 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最終會繼承:

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 (最少)。 在將異常鏈引入Throwable 之前, InvocationTargetExcpetion用於鏈接異常...

如上所述,當InvocationTargetException被改裝時,我認為語言設計者想要:

  1. 防止InvocationTargetException有兩個不同的“原因” - 一個存儲在target ,另一個存儲在cause ; 還是
  2. 與依賴於target字段的現有代碼向后兼容。

這就是為什么他們將target字段保留為真正使用並實現任何現有構造函數的target字段,以便cause字段保持為null 當然, InvocationTargetExceptiongetCause()實現會返回target作為原因。

所以回答

是否存在需要使用null原因拋出異常的用例?

不是真的,不是這個課程的用途 - 而且是 - 打算使用。

然而,這個問題仍然存在:

為什么要提供這個類的默認構造函數

此后這個構造函數似乎存在

我傾向於認為,這一類其實是相當null -tolerant。 畢竟, public構造函數允許null作為Throwable target 作為設計者,如果您已經允許,那么您也可以添加顯式為target指定nullprotected默認構造函數,從而允許繼承類來構造所需的類。

這也回答了原來的問題:

所以在我看來,InvocationTargetException.getCause()永遠不能為null。

我錯過了什么嗎?

是。 InvocationTargetException確實是有意具有非null targetcause 然而,這里“錯過”的是,遺憾的是, target (以及因此cause可以null ,因為類中的任何東西都不會強制它。

InvocationTargetException擴展了InvocationTargetException ReflectiveOperationException

核心反射中反射操作拋出的常見超類異常。

當您使用反射來調用方法(或構造函數)時。

Method method = ...
method.invoke(instance, ...);

如果方法拋出異常,它將存儲在InvocationTargetExceptiontarget字段中。 在大多數反思案例中都會發生這種情況。

有一個空構造函數的事實讓我相信它可能在其他情況下使用不同。

JDK 7

private Throwable target;

/**
 * Constructs an {@code InvocationTargetException} with
 * {@code null} as the target exception.
 */
protected InvocationTargetException() {
    super((Throwable)null);  // Disallow initCause
}

我同意你的觀點 - 我不知道InvocationTargetException如何可以為null,因為它僅在目標拋出異常時拋出。

我的猜測是getCause()的文本聲明“可能為null”只是從Throwable.getCause()Javadoc復制的樣板文件。

首先,值得一提的是,通過protected構造函數不僅允許null原因。 您還可以調用target值為nullpublic構造函數。 不會發生NullPointerException ...

話雖如此, 似乎是比一些設計師只是滑倒了。

可能是設計者想要通過反射實現類的實例化,如:

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實例並將它們傳遞給客戶端代碼,從而將特定原因相加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM