Quando devono essere utilizzati valori null di Boolean?


159

Java booleanconsente valori di truee falsementre booleano consente true, falsee null. Ho iniziato a convertire le mie booleans in Booleans. Ciò può causare arresti anomali in test come

Boolean set = null;
...
if (set) ...

mentre il test

if (set != null && set) ...

sembra inventato e soggetto a errori.

Quando, se mai, è utile usare Booleans con valori null? Se mai, quali sono i principali vantaggi dell'oggetto avvolto?

AGGIORNAMENTO: Ci sono state molte risposte preziose che ho riassunto alcune di queste nella mia risposta. Nella migliore delle ipotesi sono un intermediario in Java, quindi ho cercato di mostrare ciò che trovo utile. Nota che la domanda è "formulata in modo errato" (il valore booleano non può "avere un valore nullo") ma l'ho lasciato nel caso in cui altri abbiano lo stesso malinteso


7
A volte, si desidera uno stato non inizializzato e l'impostazione della Booleanvariabile nullaiuta.
nhahtdh,

3
"Sempre" è un po 'forte che non oso confermare, ma mi aspetterei un test nullse fosse davvero usato come terzo stato.
nhahtdh,

6
Hai un motivo per convertire i booleani in booleani? Attaccherei al tipo primitivo e lo avvolgo solo se c'è una buona ragione per farlo, ad esempio quando devo passare una variabile per riferimento.
jpe

7
Potresti anche voler dare un'occhiata a questo: thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
biziclop

6
Non esiste un "valore nullo in un valore booleano". A Booleanè un oggetto, mentre a booleanè uno "scalare". Se un Booleanriferimento è impostato su null significa che l' Booleanoggetto corrispondente non esiste. Non puoi mettere nulla dentro qualcosa che non esiste.
Hot Licks,

Risposte:


244

Usa booleanpiuttosto che Booleanogni volta che puoi. Questo eviterà molti se NullPointerExceptionrenderà il tuo codice più robusto.

Boolean è utile, per esempio

  • per archiviare i booleani in una raccolta (Elenco, Mappa, ecc.)
  • per rappresentare un valore booleano nullable (ad esempio proveniente da una colonna booleana nullable in un database). Il valore null potrebbe significare "non sappiamo se è vero o falso" in questo contesto.
  • ogni volta che un metodo richiede un oggetto come argomento e devi passare un valore booleano. Ad esempio, quando si utilizza la riflessione o metodi come MessageFormat.format().

35
Un valore nullo nel database potrebbe anche significare "FileNotFound"
Karl Johan,

31
Il tuo secondo proiettile è davvero il nucleo della risposta giusta a questa domanda, credo.
Niels Brinch,

3
Un altro uso di Boolean che ho avuto è come parametro di tipo generico quando estendo le classi generiche - strettamente correlate al punto 3.
Alex

6
Sovraccaricare il concetto di null con un significato diverso da "l'universo non lo sa" è più debole dell'uso di un enum valutato 3 (o più). Rende anche più esplicita la lettura del codice che passa i parametri nel metodo.
bluevector,

16
O # 4: Boolean isSchrodinger‎CatAlive = null;(scusa, non ho resistito;)).
Matthieu,

58

Non lo uso quasi mai Booleanperché la sua semantica è vaga e oscura. Fondamentalmente hai una logica a 3 stati: vero, falso o sconosciuto. A volte è utile usarlo quando, ad esempio, hai dato all'utente una scelta tra due valori e l'utente non ha risposto affatto e vuoi davvero conoscere quelle informazioni (pensa: colonna NULLable del database).

Non vedo alcun motivo per convertire da booleana Booleanin quanto introduce overhead di memoria aggiuntiva, possibilità di NPE e meno digitazione. In genere uso goffo BooleanUtils.isTrue()per rendere la mia vita un po 'più facile con Boolean.

L'unica ragione per l'esistenza di Booleanè la capacità di avere raccolte di Booleantipo (i generici non consentono boolean, così come tutti gli altri primitivi).


1
È una libreria esterna (beni comuni Apache), però.
nhahtdh,

4
Per la logica multivalore è preferibile usare enum. Pertanto, Boolean dovrebbe essere lasciato per le variabili (automatiche) di boxe da utilizzare nelle strutture di dati.
jpe

39
Quando si utilizza Boolean, un comodo test per evitare eccezioni del puntatore null è Boolean.TRUE.equals(myBooleanObject)o Boolean.FALSE.equals(myBooleanObject).
Christopher Peisert,

10
Un oggetto booleano ha solo due stati - truee false. nonnull è uno stato dell'oggetto, ma piuttosto uno stato del riferimento oggetto.
Hot Licks,

2
Lasciare che Apache Commons sia come "Qualcuno potrebbe rovinare la valutazione dei booleani ... facciamo un isTrue()metodo ..." che suona come la cosa più stupida della storia delle funzioni di utilità. Eppure, in qualche modo, è utile ... questo è il più grande peso qui.
corsiKa

33

Wow, che diamine? Sono solo io o tutte queste risposte sono sbagliate o almeno fuorvianti?

La classe booleana è un wrapper attorno al tipo primitivo booleano. L'uso di questo wrapper è in grado di passare un valore booleano in un metodo che accetta un oggetto o un generico. Cioè vettore.

Un oggetto booleano non può MAI avere un valore null. Se il tuo riferimento a un booleano è nullo, significa semplicemente che il tuo booleano non è mai stato creato.

Questo potrebbe essere utile: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Boolean.java

Un riferimento booleano nullo deve essere utilizzato solo per attivare una logica simile alla quale si dispone di qualsiasi altro riferimento null. Usarlo per la logica a tre stati è goffo.

EDIT: avviso, questa Boolean a = true;è una dichiarazione fuorviante. Questo equivale a qualcosa di più vicino a Boolean a = new Boolean(true); Si prega di consultare l'autoboxing qui: http://it.wikipedia.org/wiki/Boxing_%28computer_science%29#Autoboxing

Forse è qui che proviene gran parte della confusione.

EDIT2: leggi i commenti qui sotto. Se qualcuno ha un'idea di come ristrutturare la mia risposta per incorporarla, per favore fallo.


2
Non capisco la tua affermazione "Un booleano non può MAI avere un valore null". Posso creare un booleano ( Boolean a = true;) e quindi impostare un su null ( a = null;). Potrebbe non essere elegante o saggio, ma è possibile.
peter.murray.rust,

7
Quando lo fai Boolean a; a è un puntatore a un oggetto booleano. Se non a = null;hai impostato il tuo valore booleano su null, hai impostato il riferimento su null. Do Boolean a = null; a.booleanValue();In questo caso, è mai stato creato un oggetto booleano e quindi ti lancia una NullPointerException. Fammi sapere se hai bisogno di ulteriori istruzioni.
user606723

Inoltre, quando lo fai Boolean a = true;, fa una sorta di magia che in realtà viene interpretata come Boolean a = new Boolean(true);probabilmente non completamente corretta per motivi di performance, ma devi capire che il booleano è ancora un oggetto.
user606723

7
@missingno, tutto il codice che si occupa di qualsiasi oggetto deve occuparsene. Un riferimento a un oggetto può essere nullo o no. Questo non è un caso speciale e non richiede una considerazione speciale.
user606723

3
Ti manca il mio punto @missingno. Sono d'accordo che dobbiamo considerare valori di riferimento nulli. Non ho mai discusso contro questo. Ma dobbiamo farlo per QUALSIASI RIFERIMENTO A OGGETTI. Un riferimento booleano nullo non è un caso speciale. E quindi valori di riferimento booleani nulli non richiedono una considerazione speciale.
user606723

24

Esistono tre motivi rapidi:

  • per rappresentare valori booleani database, che può essere true, falseonull
  • per rappresentare i xsd:booleanvalori dello schema XML dichiarati conxsd:nillable="true"
  • per poter usare tipi generici: List<Boolean>- non puoi usareList<boolean>

Ho scritto esplicitamente "booleano", non " boolean" (stile mentale), perché in Oracle di solito usi char(1) nulli valori "T" e "F". Quindi potrebbe essere (con ad es. Un adattatore di tipo Hibernate) null :)
Grzegorz Grzybek

2
Quale database non consente null per booleano? Se imposti la colonna come nullable, il tipo di dati non ha più importanza ...
Michal B.

@MichalB. Tipo di bit Sybase (e SQL Server) infocenter.sybase.com/help/index.jsp?topic=/…
mmmmmm

@Mark - no, SQL Server consente un bit nullable - msdn.microsoft.com/en-us/library/ms177603.aspx
David M

11

RISPOSTA ALLA PROPRIA DOMANDA: ho pensato che sarebbe stato utile rispondere alla mia domanda dato che ho imparato molto dalle risposte. Questa risposta ha lo scopo di aiutare coloro - come me - che non hanno una comprensione completa dei problemi. Se uso un linguaggio errato, correggimi.

  • Il "valore" nullo non è un valore ed è sostanzialmente diverso da truee false. È l'assenza di un puntatore agli oggetti. Pertanto, pensare che il valore booleano sia 3-valore è fondamentalmente sbagliato
  • La sintassi per Boolean è abbreviata e nasconde il fatto che il riferimento punta a Oggetti:

    Boolean a = true;

nasconde il fatto che trueè un oggetto. Altri incarichi equivalenti potrebbero essere:

Boolean a = Boolean.TRUE;

o

Boolean a = new Boolean(true);
  • La sintassi abbreviata

    if (a) ...

è diverso dalla maggior parte degli altri compiti e nasconde il fatto che a potrebbe essere un riferimento a un oggetto o una primitiva. Se un oggetto è necessario verificare per nullevitare NPE. Per me è psicologicamente più facile ricordarlo se esiste un test di uguaglianza:

if (a == true) ...

dove ci potrebbe essere richiesto di testare null. Quindi la forma abbreviata è sicura solo quando aè primitiva.

Per me ora ho i consigli:

  • Non usare mai null per una logica a 3 valori. Usa solo vero e falso.
  • Non tornare MAI Booleanda un metodo come potrebbe essere null. Solo ritorno boolean.
  • Utilizzare solo Booleanper avvolgere elementi in contenitori o argomenti per metodi in cui sono richiesti oggetti

5
Non usare "new Boolean (qualunque cosa)". Ciò creerà un'istanza di un nuovo booleano nell'heap. Eppure Boolean è immutabile. Usa "Boolean.valueOf (qualunque)" che creerà un riferimento che punta a Boolean.TRUE o Boolean.False a seconda di qualunque cosa.
simbo1905,

1
Uno dei molti problemi con Java (IMHO dopo 12 anni) è l'incoerenza dell'approccio ai valori null che hanno anche le vecchie lingue. Dando un'occhiata a Scala, ha il concetto di un'opzione digitata che può essere nulla o può avere un valore (sottoclassi None o Some). Quindi puoi chiamare myOption.getOrElse (defaultValue). Vedi scala-lang.org/api/current/scala/Option.html non c'è nulla di complesso in questa funzione. Tuttavia, poiché è integrato nel nuovo linguaggio JVM, molte librerie lo utilizzano. Ciò rende la "correzione" in scala del problema "Java del secolo scorso", ma si compila ancora in file di classe che vengono eseguiti su JRE.
simbo1905,

10

Le classi wrapper per primitive possono essere utilizzate dove sono richiesti oggetti, le raccolte sono un buon esempio.

Immaginate il necessario per qualche negozio motivo una sequenza di booleanin un ArrayList, questo può essere fatto da boxe booleanin Boolean.

Ci sono alcune parole su questo qui

Dalla documentazione:

Come tutti i programmatori Java sanno, non è possibile inserire un int (o altro valore primitivo) in una raccolta. Le raccolte possono contenere solo riferimenti a oggetti, quindi devi racchiudere i valori primitivi nella classe wrapper appropriata (che è Integer nel caso di int). Quando togli l'oggetto dalla collezione, ottieni l'Integer che hai inserito; se hai bisogno di un int, devi decomprimere l'Integer usando il metodo intValue. Tutto questo pugilato e unboxing è una seccatura e ingombra il tuo codice. La funzione di autoboxing e unboxing automatizza il processo, eliminando il dolore e il disordine.

http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html


3

Booleanwrapper è utile quando si desidera stabilire se il valore è stato assegnato o meno a parte truee false. Ha i seguenti tre stati:

  • Vero
  • falso
  • Non definito quale sia null

Considerando che booleanha solo due stati:

  • Vero
  • falso

La differenza di cui sopra lo renderà utile in Elenchi di Booleanvalori, che possono avere True, Falseo Null.


No, non ha uno stato nullo, questo è il riferimento.
Matsemann,

Quello che intendevo era Bolean può essere usato per definito True / False e Not Defined.
Ramesh PVK,

3

Suppongo che in alcuni casi dovresti avere un meccanismo per distinguere un campo booleano che ha già impostato valore o no.


1

Lo scopo principale di Boolean è il valore null. Il valore null indica che la proprietà non è definita , ad esempio prendere la colonna nullable del database.

Se hai davvero bisogno di convertire tutto da booleano primitivo a booleano wrapper, puoi usare il seguente codice per supportare il vecchio codice:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...

6
"Lo scopo principale è un valore nullo". No, lo scopo principale di Boolean è passare un riferimento a un booleano come oggetto.
user606723,

@utente606723 concordato, mi riferivo al caso del database nella mia mente mentre stavo scrivendo.
JMelnik,

1

Ci sono molti usi per il valore ** null ** nel wrapper booleano! :)

Ad esempio, potresti avere in una forma un campo chiamato "newsletter" che indica se l'utente desidera o meno una newsletter dal tuo sito. Se l'utente non seleziona un valore in questo campo, potresti voler implementare un comportamento predefinito in quella situazione (invia? Non inviare?, Domanda di nuovo ?, ecc.). Chiaramente, non impostato (o non selezionato o ** null **), non è lo stesso che vero o falso.

Ma, se "non impostato" non si applica al tuo modello, non modificare la primitiva booleana;)


1

In una definizione rigorosa di un elemento booleano, ci sono solo due valori. In un mondo perfetto, sarebbe vero. Nel mondo reale, l'elemento potrebbe essere mancante o sconosciuto. In genere, ciò comporta l'input dell'utente. In un sistema basato su schermo, potrebbe essere forzato da una modifica. In un mondo batch che utilizza un database o un input XML, l'elemento potrebbe facilmente mancare.

Quindi, nel mondo non perfetto in cui viviamo, l'oggetto booleano è fantastico in quanto può rappresentare lo stato mancante o sconosciuto come nullo. Dopotutto, i computer modellano semplicemente il mondo reale e dovrebbero tenere conto di tutti gli stati possibili e gestirli con eccezioni di lancio (soprattutto perché ci sono casi d'uso in cui il lancio dell'eccezione sarebbe la risposta corretta).

Nel mio caso, l'oggetto booleano era la risposta perfetta poiché a volte l'input XML aveva l'elemento mancante e potevo ancora ottenere un valore, assegnarlo a un valore booleano e quindi verificare la presenza di un valore null prima di provare a utilizzare un test vero o falso con esso .

Solo i miei 2 centesimi.


1

Per tutte le buone risposte sopra, ho intenzione di dare un esempio concreto nella HttpSessionclasse servlet Java . Spero che questo esempio aiuti a chiarire alcune domande che potresti avere ancora.

Se è necessario archiviare e recuperare valori per una sessione, utilizzare il metodo setAttribute(String, Object) e getAttribute(String, Object). Quindi, per un valore booleano, sei costretto a utilizzare la classe booleana se desideri memorizzarla in una sessione http.

HttpSession sess = request.getSession(false);
Boolean isAdmin = (Boolean) sess.getAttribute("admin");
if (! isAdmin) ...

L'ultima riga causerà a NullPointerExceptionse i valori dell'attributo non sono impostati. (che è il motivo che mi ha portato a questo post). Quindi lo stato logico 3 è qui per rimanere, che tu preferisca usarlo o no.


0

Il modo migliore sarebbe quello di evitare completamente i booleani, poiché ogni booleano implica che hai una dichiarazione condizionale in qualsiasi altra parte del tuo codice (vedi http://www.antiifcampaign.com/ e questa domanda: puoi scrivere qualsiasi algoritmo senza una dichiarazione if ? ).

Tuttavia, pragmaticamente devi usare i booleani di volta in volta, ma, come hai già scoperto da solo, trattare con i booleani è più soggetto a errori e più ingombrante. Quindi suggerirei di usare booleani ove possibile. Eccezioni da ciò potrebbero essere un database legacy con colonne booleane nullable, anche se proverei a nasconderlo anche nella mia mappatura.


Trattare con i booleani è soggetto a errori quanto a qualsiasi altro oggetto. A proposito, il collegamento è contrario alla proliferazione di IF per il controllo del tipo, non per un uso generale. E a sua volta, questo è "pericoloso" perché rende le modifiche più difficili. Quindi non c'è nulla di sbagliato negli IF di per sé.
Mister Smith,

Non una risposta alla domanda.
Matsemann,

@MisterSmith Imho che un flag booleano viene spesso utilizzato in modo errato come variabile di controllo del tipo, quindi il link può essere applicato anche qui. Dovrebbe essere solo un indizio che si dovrebbe pensare se un booleano sia lo strumento giusto in una determinata situazione. L'affermazione "evitare completamente i booleani" è ovviamente molto radicale e praticamente impossibile, motivo per cui ho aggiunto il secondo paragrafo. Ho anche aggiunto un "più incline all'errore e più ingombrante" per chiarire le cose.
Roland Schneider,

0

Boolean può essere molto utile quando hai bisogno di tre stati. Come nel test del software se Test è passato invia true, se fallito invia false e se caso test interrotto invia null che indica caso test non eseguito.


2
Gli enum non sarebbero i migliori per questo? Al contrario di produrre inaspettatamente NullPointerExceptions per un client, enum avrebbe definito esplicitamente "stati"
Kartik Chugh

Preferisci sempre gli enum invece dei booleani nelle macchine statali. Non si sa mai quando arriva un nuovo quarto stato nel requisito aziendale.
AnupamChugh
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.