2013-07-16 14 views
7

Zgodnie z javadocs, InvocationTargetException.getCause() może być zerowy:Kiedy jest InvocationTargetException.getCause() null?

Zwraca przyczynę tego wyjątku (rzucony wyjątkiem tarczy, która może być zerowa).

ale dokumentacja mówi również, że owija istniejący wyjątek:

InvocationTargetException jest sprawdzana wyjątek, który owija wyjątek rzucony przez wywoływanego metody lub konstruktora.

Więc wydaje mi się, że InvocationTargetException.getCause()nigdy nie może być null.

Czy czegoś brakuje?

UPDATE

Tak, coś mi umknęło - domyślny konstruktor InvocationTargetException spowodowałoby getCause() być zerowa.

Mam teraz pytanie, dlaczego w ogóle podać domyślny konstruktor dla tej klasy. Czy istnieje przypadek, w którym wyjątek musi zostać zgłoszony z przyczyną zerową?

+1

Można po prostu "rzucić nowe InvocationTargetException()', który jest chronionym konstruktorem. –

+0

Pominięto domyślny konstruktor, który spowodowałby to, ale teraz nie mogę zrozumieć, co to jest domyślny konstruktor. –

+0

Może to być możliwe. Dlaczego projektanci języków robią rzeczy trudno odpowiedzieć. –

Odpowiedz

1

InvocationTargetException rozciąga ReflectiveOperationException który stanowi

Common superklasę wyjątków rzucanych przez operacje odblaskowych w podstawowej refleksji.

Kiedy używasz odbicia, aby wywołać metodę (lub konstruktor).

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

Jeżeli sposób zwrócił wyjątek, że będzie przechowywany w dziedzinie InvocationTargetExceptiontarget. To się stanie w większości przypadków refleksji.

Fakt, że istnieje pusty konstruktor, pozwala mi sądzić, że w innych przypadkach może być inaczej używany.

JDK 7

private Throwable target; 

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

Uwaga - to jest teraz publicznej w OpenJDK - więc może to być błąd ... – xtravar

0

zgadzam się z tobą - nie widzę jak InvocationTargetException może kiedykolwiek być null, ponieważ jest rzucony tylko gdy cel zgłasza wyjątek.

Moje przypuszczenie jest takie, że tekst dla getCause(), który stwierdza "który może być pusty" jest po prostu wzorcem skopiowanym z pliku Javadoc Throwable.getCause().

+0

Jak inni zwrócili uwagę jest co najmniej składniowym możliwość, że getCause może być null, ale nie widzę punktu pozwalając go –

0

Po pierwsze, warto wspomnieć, że przyczyną jest nie tylko null przyczyna za pośrednictwem konstruktora protected. Można również wywoływać konstrukcje public z wartością target o wartości null. Nie pojawi się NullPointerException ...

Powiedziawszy to, to czy wydaje się czymś więcej niż coś, co projektanci właśnie wymknęli.

Może być tak, że projektanci chcieli włączyć instancji klasy za pośrednictwem refleksji, jak w:

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(); 

ten sposób util metoda może tworzyć InvocationTargetException instancji i przekazać je do kodu klienta, który dodaje się do konkretnej przyczyny.

+0

to wydaje się być jedynym prawdopodobnym powodem, ale to nadal nie jest jasne, co USECASE wymagałoby przy użyciu odbicia do skonstruowania instancji używany domyślny no-param konstruktor –

+0

@MiserableVariable [Hibernate 3.5 czynili to] (http: // docs. jboss.org/hibernate/core/3.5/reference/en/html/persistent-classes.html#persistent-classes-pojo-constructor);) (i [w niektórych miejscach nadal ma ...] (http: // docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html_single/#d5e590)), ale nie dla 'InvocationTargetException'. – yair

+0

Tworzenie obiektów, nawet wyjątków, przez odbicie nie jest może niezwykłe. Ale żadna z odpowiedzi nie odpowiada na moje pytanie, IMHO, co jest wprawdzie nieco subiektywne. –

1

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:

  1. 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ą nulltarget 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.

+0

Dzięki za bardzo szczegółową analizę! Wierzę, że jesteś prawie na dobrej drodze, a ostatni akapit podsumowuje całkiem ładnie. –

Powiązane problemy