So.
@ xtravar's comment on my (much) earlier answer spowodował, że trzeba jeszcze raz przyjrzeć się temu problemowi. I mógłbym to dostać. Proszę, weź mnie.
Został wprowadzony do Javy bardzo wcześnie. Przynajmniej tak wcześnie, jak w przypadku niektórych JDK 1.1.X, które pochodzą z dowolnego miejsca between February 1997 to December 1998. Skąd mam wiedzieć, że to takie stare? W końcu na klasie nie ma oznaczenia @since 1.1
.
zdarzyło mi się zobaczyć następujące javadoc na polu serialVersionUID
:
/**
* Use serialVersionUID from JDK 1.1.X for interoperability
*/
prawo. Więc co?
Tak, zgodnie z docs Throwable.getCause()
, które InvocationTargetException
ostatecznie dziedziczy:
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
Teraz należy połączyć to z dopiskiem na InvocationTargetException
klasy dokumentów:
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."
Zobacz gdzie mi chodzi ?
Notatka na temat Throwable.getCause()
ma dokładnie wartość InvocationTargetException
(najmniej). InvocationTargetExcpetion
użyto do wyjątków łańcuchowych przed wyjątek-łańcuchowym został wprowadzony do Throwable
...
A kiedy InvocationTargetException
została zmodernizowana, jak zauważono, zakładam, że projektanci chcieli język:
- zapobiec możliwości z
InvocationTargetException
mającym dwie różne "przyczyny" - jedną przechowywaną w target
, a drugą w cause
; i nadal jest kompatybilna wstecz z istniejącym kodem, który bazuje na polu .
Dlatego opuścili pole target
jak ten, który naprawdę wykorzystane i wdrożone wszelkich istniejących konstruktorów tak, że pole cause
pozostaje null
na dobre. Implementacja getCause()
dla InvocationTargetException
, oczywiście, powoduje, że przyczyną jest target
.
Więc odpowiedzieć
Czy istnieje USECASE gdzie musi być wyjątek wyrzucony z pustym przyczyny?
Nie naprawdę, to nie jest jak klasa jest - i było - przeznaczone być używany.
A jednak, to pozostaje pytanie:
dlaczego dostarczyć domyślnego konstruktora dla tej klasy w ogóle
(i this constructor seems to exist ever since)
I mają tendencję do myślenia, że ta klasa jest w rzeczywistości dość null
- tolerancyjny. Po tym wszystkim, public
konstruktorzy pozwolenia null
jako Throwable target
. Jako projektant, jeśli już dozwolone, że możesz także dodać konstruktora protected
domyślnego, który wyraźnie przypisuje null
do target
, umożliwiając klas dziedziczących zbudować klasę jednak potrzebne.
ten odpowiada również oryginalne pytanie:
Więc wydaje mi się, że InvocationTargetException.getCause() nigdy może być null.
Czy brakuje mi czegoś?
Tak. InvocationTargetException
rzeczywiście przeznaczony mieć niebędącą null
target
i cause
. Jednak tutaj "brakowało" tego, że target
(i tym samym cause
) niestety może być być null
, ponieważ nic w klasie nie zmusza go inaczej.
Można po prostu "rzucić nowe InvocationTargetException()', który jest chronionym konstruktorem. –
Pominięto domyślny konstruktor, który spowodowałby to, ale teraz nie mogę zrozumieć, co to jest domyślny konstruktor. –
Może to być możliwe. Dlaczego projektanci języków robią rzeczy trudno odpowiedzieć. –