Sprawdź, czy null Boolean jest true powoduje wyjątek


169

Mam następujący kod:

Boolean bool = null;

try 
{
    if (bool)
    {
        //DoSomething
    }                   
} 
catch (Exception e) 
{
    System.out.println(e.getMessage());             
}

Dlaczego moje sprawdzenie zmiennej boolowskiej „bool” powoduje wyjątek? Czy nie powinien po prostu przeskoczyć bezpośrednio obok wyrażenia if, kiedy „widzi”, że nie jest prawdą? Kiedy usuwam instrukcję if lub sprawdzam, czy NIE jest pusta, wyjątek znika.


3
Wszystkie powyższe odpowiedzi dotyczące rozpakowywania obiektów są poprawne. Jednak ze względu na kompletność można również zmienić kod tak, aby używał pierwotnego „boolowskiego” zamiast opakowania obiektu „Boolean”. Powinieneś także przypomnieć sobie różnicę między prymitywem a obiektem.
Marvo

Tymczasem ... if (bool == Boolean.TRUE)ocenia fałsz bez generowania wyjątku. Nie jestem pewien, czy było to zamierzone w przypadku, który właśnie znalazłem.
simon.watts

2
@ simon.watts, które byłoby fałszywe bool, nullgdyby Booleanbyło OR, gdyby zostało skonstruowane jawnie (a nie jako odniesienie do Boolean.TRUE). Więc nie zalecane; w przeciwieństwie do tego, if (Boolean.TRUE.equals(bool))który działałby zgodnie z oczekiwaniami, w tym bezpieczną obsługę nullwartości.
StaxMan

Odpowiedzi:


171

Kiedy masz boolean, może to być albo truealbo false. Jednak, gdy masz Booleanto może być Boolean.TRUE, Boolean.FALSElub nulljak każdy inny przedmiot.

W Twoim konkretnym przypadku instrukcja Booleanjest nulli ifinstrukcja wyzwala niejawną konwersję do booleantego, co tworzy NullPointerException. Zamiast tego możesz potrzebować:

if(bool != null && bool) { ... }

23
Z technicznego punktu Booleanwidzenia a może być dowolną liczbą prawdziwych instancji, a nie tylko Boolean.TRUE. Na przykład new Boolean(true).
Steve Kuo

1
Trudno mi zrozumieć, dlaczego if (myBoolean)(gdzie myBooleanjest Boolean) nie zgłasza błędu kompilatora lub przynajmniej ostrzeżenia. To na pewno pułapka.
Josh M.,

1
@JoshM. To dlatego, że Java ma Boks i unboxing z owijarki: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius

3
@Vinicius pewnie, ale kompilator powinien albo w tym przypadku zrobić dla nas wartość null, przynajmniej przez ostrzeżenie kompilatora.
Josh M.,

2
@JoshM. Nie mogę się bardziej zgodzić :)
Vinicius

402

Jeśli nie lubisz dodatkowych sprawdzeń zerowych:

if (Boolean.TRUE.equals(value)) {...}

1
@AvrDragon: czy jest wymagane? Operator == działa tutaj, ponieważ Boolean ma tylko dwie wartości
Atul

7
@Atul Tak, tutaj wymagane jest równe. Ponieważ (new Boolean (true) == new Boolean (true)) jest .... false. Przyczyna: Boolean jest tylko klasą i może mieć wiele instancji, jak każda inna klasa w Javie.
AvrDragon

35
tak, szkoda, konstruktor powinien być prywatny, więc zapewniono, że to twingleton ...
fortran

15
@fortran +1 dla „twingleton”.
Bennett McElwee,

1
Nie ma absolutnie sensu używać Apache BooleanUtils nad tym idiomem.
StaxMan

82

Użyj Apache BooleanUtils .

(Jeśli najwyższa wydajność jest najważniejszym priorytetem w Twoim projekcie, spójrz na jedną z pozostałych odpowiedzi dotyczących rozwiązania natywnego, które nie wymaga dołączania biblioteki zewnętrznej).

Nie odkrywaj na nowo koła. Wykorzystaj to, co już zostało zbudowane i używaj isTrue():

BooleanUtils.isTrue( bool );

Sprawdza, czy Booleanwartość jest prawdziwa, obsługa nullprzez zwracanie false.

Jeśli nie jesteś ograniczony do bibliotek, które „możesz” dołączyć, istnieje kilka świetnych funkcji pomocniczych do wszelkiego rodzaju zastosowań, w tym Booleansi Strings. Proponuję przejrzeć różne biblioteki Apache i zobaczyć, co już oferują.


59
Ponowne wynalezienie koła nie wydaje się takie złe, gdy alternatywą jest użycie zewnętrznej biblioteki do czegoś tak podstawowego jak to.
Paul Manta,

3
@PaulManta Zgadzam się, jeśli jest to jedyna rzecz, której kiedykolwiek używałbyś w bibliotekach Apache Utils, ale sugerowanym pomysłem jest „przeglądanie” bibliotek, aby uzyskać dostęp do innych przydatnych funkcji.
Joshua Pinter

1
Korzystanie z tych bibliotek wiąże się z obniżeniem wydajności. Tak więc w przypadku takich podstawowych rzeczy, które są częścią języka, nie powinieneś używać bibliotek.
ACV

6
Ta biblioteka na nowo odkrywa koło. Staram się jak najbardziej unikać takich bibliotek.
mschonaker

3
@mschonaker Jeśli Apache BooleanUtils wymyśla koło na nowo, jakie jest oryginalne koło? Chodzi o to, aby uniknąć tworzenia wielu funkcji pomocniczych, które naśladują to, co zostało już zrobione w bibliotekach, takich jak ta. Korzystam również toStringYesNoz tej biblioteki we wszystkich moich aplikacjach.
Joshua Pinter

13

Booleantypy mogą być null. Musisz nullsprawdzić, jak ustawiłeś null.

if (bool != null && bool)
{
  //DoSomething
}                   

3
Co jest nie tak z tą odpowiedzią? To nie sprawdzanie wartości bool spowodowałoby wyrzucenie wyjątku. Niepotrzebne głosy przeciw.
dodexahedron

2
Zgadzam się, że to całkiem rozsądna odpowiedź. Możesz jednak pozbyć się obsługi wyjątków.
Marvo

14
Obsługa wyjątków jest niepotrzebna, a poza tym odbywa się w sposób, który jest złym przykładem dla początkujących. To zasługuje na złą opinię, IMO. (Tak ... wiem, że pochodzi z przykładowego kodu, ale powtórzenie go w odpowiedzi wydaje się go wspierać.)
Stephen C,

1
Jaki jest więc właściwy sposób? Nie widzę tutaj twojej odpowiedzi.
Marvo

5
Właściwy sposób to ten powyżej ... bez obsługi wyjątków. Ponadto obsługa wyjątków jest zbyt ogólna i odradzana.
vellvisher

8

Lub dzięki mocy Java 8 Optional możesz również zrobić taką sztuczkę:

Optional.ofNullable(boolValue).orElse(false)

:)


5

Boolean to klasa opakowania obiektu dla prymitywnych wartości logicznych. Ta klasa, jak każda klasa, może rzeczywiście być zerowa. Ze względu na wydajność i pamięć zawsze najlepiej jest używać prymitywu.

Klasy opakowujące w Java API służą dwóm głównym celom:

  1. Zapewnienie mechanizmu „zawijania” wartości pierwotnych w obiekcie, tak aby prymitywy mogły być włączane do działań zarezerwowanych dla obiektów, na przykład dodawane do kolekcji lub zwracane z metody z wartością zwracaną przez obiekt.
  2. Zapewnienie zestawu funkcji użytkowych dla prymitywów. Większość z tych funkcji jest związanych z różnymi konwersjami: konwertowaniem prymitywów do iz obiektów typu String oraz konwertowanie prymitywów i obiektów typu String na iz różnych baz (lub podstawników), takich jak binarne, ósemkowe i szesnastkowe.

http://en.wikipedia.org/wiki/Primitive_wrapper_class


0

ponieważ zmienna bool wskazuje na null, zawsze otrzymasz wyjątek NullPointerException, musisz najpierw zainicjować zmienną gdzieś z wartością niezerową, a następnie ją zmodyfikować.


1
Gdyby tak było, catchblok obsługiwałby wyjątek NullPointerException. Problem polega na tym, że OP próbuje rozpakować odniesienie zerowe do prymitywu.
Mike Adler

„zawsze będziesz” - nie zawsze, z wyjątkiem przykładowego, uproszczonego kodu, który nie robi nic pomiędzy inicjalizacją zmiennej nulla jej testowaniem. Przypuszczalnie prawdziwy kod nie byłby taki prosty lub cały iftest mógłby zostać usunięty.
nnnnnn
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.