Dlaczego mogę wrzucać null w Javie?
Podczas uruchamiania tego:
public class WhatTheShoot {
public static void main(String args[]){
try {
throw null;
} catch (Exception e){
System.out.println(e instanceof NullPointerException);
System.out.println(e instanceof FileNotFoundException);
}
}
}
Odpowiedź brzmi:
true
false
Co było dla mnie oszałamiające. Myślałem, że to spowoduje błąd w czasie kompilacji.
Dlaczego mogę wrzucić null w Javie i dlaczego upcast go do NullPointerException?
(W sumie Nie wiem czy to jest "upcast", biorąc pod uwagę, że rzucam null)
Poza bardzo durnym pytaniem w wywiadzie (proszę, nikt tego nie zadaje w wywiadzie) nie widzę żadnego powód throw null
. Może chcesz być zwolniony, ale tak jest... Dlaczego ktoś inny miałby to robić?
Ciekawostka IntelliJ IDEA 12 mówi mi, że moja linia, e instanceof NullPointerException
, zawsze będzie fałszywa. Co wcale nie jest prawdą.
7 answers
Wygląda na to, że nie jest to null
traktowane jako NullPointerException
, ale akt próby throw null
itself rzuca NullPointerException
.
Innymi słowy, throw
sprawdza, czy jego argument jest nonnull, a jeśli jest null, rzuca NullPointerException
.
JLS 14.18 określa to zachowanie:
Jeśli ocena wyrażenia zakończy się normalnie, tworząc wartość null, wtedy instancja V' klasy NullPointerException jest tworzona i wyrzucana zamiast null. Na throw statement następnie kończy się nagle, powodem jest rzut z wartością V'.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-10 17:24:11
Dlaczego upcast it to a NullPointerException?
Zgodnie z JLS 14.18:
Instrukcja throw najpierw ocenia wyrażenie. Jeśli z jakiegoś powodu ocena wyrażenia kończy się nagle, to rzut kończy się nagle z tego powodu. Jeśli ewaluacja wyrażenia zakończy się normalnie, tworząc wartość inną niż null V, to polecenie throw kończy się nagle, powodem jest rzut z wartością V. Jeśli ewaluacja Wyrażenie kończy się normalnie, wytwarzając wartość null, wtedy instancja V' klasy NullPointerException jest tworzona i wyrzucana zamiast null. polecenie throw kończy się nagle, powodem jest rzut z wartością V'.
Dlaczego mogę wrzucać null w Javie ?
Możesz rzucać obiekty typu Throwable
, a ponieważ null
jest poprawnym odniesieniem do Throwable
, kompilator na to pozwala.
Tak mówi Neal Gafter
chociaż null jest przypisywany do każdego typu odniesienia, Typ null sam w sobie nie jest typem odniesienia. Naszym zamiarem było, aby wymóg, aby wyrażenie w deklaracji throw było typem referencyjnym, został usunięty z trzeciego wydania JLS, ale ta zmiana nigdy nie weszła do opublikowanej wersji. Tak więc jest to błąd kompilatora javac, który wprowadziłem w SE 5.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-11 08:30:51
Zachowuje się zgodnie z JLS:
Jeśli ocena wyrażenia zakończy się normalnie, tworząc wartość null, wtedy instancja V' klasy NullPointerException jest tworzona i wyrzucana zamiast null.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-10 17:22:56
Myślenie o tym w ten sposób sprawia, że trochę bardziej oczywiste jest, dlaczego to działa:
try {
Exception foo = null;
if(false) {
foo = new FileNotFoundException();
} // Oops, forgot to set foo for the true case..
throw foo;
} catch (Exception e){
System.out.println(e instanceof NullPointerException);
System.out.println(e instanceof FileNotFoundException);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-10 22:19:14
Nie wiem na pewno, ale domyślam się, że "throw null"; działa a nie i próba tego powoduje, że program wyrzuca wyjątek, a tym wyjątkiem jest (drum roll) NullPointerException...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-10 17:18:30
null może być rzucane na cokolwiek*, łącznie z wyjątkiem. Tak jak możesz zwrócić null jeśli podpis metody określa, że powinieneś zwrócić wyjątek (lub rzeczywiście łańcuch znaków lub klasę Person), możesz go wyrzucić.
*z wyłączeniem typów prymitywnych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-12 15:12:29
Bharal...It wygląda na błąd kompilatora javaca. Myślę, że został wprowadzony w SE 5. Null może być przypisany do dowolnego typu odniesienia. Jednak "Typ null" sam w sobie nie jest typem referencyjnym. Program kompiluje je, ponieważ null może po prostu rzucić w wyjątek. Ponadto throw szuka odniesienia do obiektu po deklaracji i ponieważ null może działać jako odniesienie do obiektu wyświetla wynik.
The JLS doc about throw as:
" Instrukcja throw najpierw ocenia Ekspresja. Jeżeli ocena wyrazu kończy się nagle z jakiegoś powodu, wtedy rzut kończy się nagle z tego powodu. Jeżeli ocena wyrażenia kończy się normalnie, wytwarzając wartość nie null V, wtedy rzut oświadczenie kończy się nagle, powodem jest rzut z wartością V. Jeśli ewaluacja wyrażenia zakończy się normalnie, otrzymamy null wartość, wtedy powstaje instancja V' klasy NullPointerException i rzucony zamiast null. Rzut oświadczenie następnie uzupełnia nagle, powodem jest rzut z wartością V'."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-26 10:43:47