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

Author: Peter Mortensen, 2013-07-10

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'.

 395
Author: Louis Wasserman,
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.

 93
Author: NINCOMPOOP,
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.

 21
Author: assylias,
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);
}
 18
Author: Nick Gotch,
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...

 13
Author: ajb,
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.

 -3
Author: Marc,
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'."

 -3
Author: techhunter,
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