Wann sollten Nullwerte von Boolean verwendet werden?

159

Java booleanermöglicht Werte trueund falsewährend Boolean ermöglicht true, falseund null. Ich habe begonnen, mein booleans in Booleans umzuwandeln . Dies kann bei Tests wie z

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

während des Tests

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

scheint erfunden und fehleranfällig.

Wann, wenn überhaupt, ist es sinnvoll, Booleans mit Nullwerten zu verwenden? Wenn nie, was sind dann die Hauptvorteile des verpackten Objekts?

UPDATE: Es gab so viele wertvolle Antworten, dass ich einige davon in meiner eigenen Antwort zusammengefasst habe. Ich bin bestenfalls ein Intermediate in Java, also habe ich versucht, die Dinge zu zeigen, die ich nützlich finde. Beachten Sie, dass die Frage "falsch formuliert" ist (Boolean kann keinen "Nullwert" haben), aber ich habe sie belassen, falls andere das gleiche Missverständnis haben

peter.murray.rust
quelle
7
Manchmal möchten Sie einen nicht initialisierten Status und das Festlegen einer BooleanVariablen als nullhilfreich.
nhahtdh
2
"Immer" ist ein bisschen stark, das ich nicht zu bestätigen wage, aber ich würde einen Test erwarten, nullwenn es wirklich als 3. Zustand verwendet wird.
nhahtdh
6
Haben Sie einen Grund, Boolesche Werte in Boolesche Werte umzuwandeln? Ich würde mich an den primitiven Typ halten und ihn nur umbrechen, wenn es einen guten Grund dafür gibt, z. B. wenn ich eine Variable als Referenz übergeben muss.
Jpe
7
Vielleicht möchten Sie auch Folgendes
biziclop
6
Es gibt keinen "Nullwert in einem Booleschen Wert ". A Booleanist ein Objekt, während a booleanein "Skalar" ist. Wenn eine BooleanReferenz auf null gesetzt ist, bedeutet dies, dass das entsprechende BooleanObjekt nicht vorhanden ist. Sie können nichts in etwas platzieren, das nicht existiert.
Hot Licks

Antworten:

244

Verwenden Sie booleananstatt Booleanjedes Mal, wenn Sie können. Dies vermeidet viele NullPointerExceptions und macht Ihren Code robuster.

Boolean ist zum Beispiel nützlich

  • Boolesche Werte in einer Sammlung speichern (Liste, Karte usw.)
  • um einen nullbaren Booleschen Wert darzustellen (der beispielsweise aus einer nullbaren booleschen Spalte in einer Datenbank stammt). Der Nullwert könnte in diesem Zusammenhang bedeuten "wir wissen nicht, ob es wahr oder falsch ist".
  • Jedes Mal, wenn eine Methode ein Objekt als Argument benötigt und Sie einen booleschen Wert übergeben müssen. Zum Beispiel bei der Verwendung von Reflexion oder Methoden wie MessageFormat.format().
JB Nizet
quelle
35
Ein Nullwert in der Datenbank könnte auch "FileNotFound"
Karl Johan
31
Ihre zweite Kugel ist wirklich der Kern der richtigen Antwort auf diese Frage, denke ich.
Niels Brinch
3
Eine andere Verwendung für Boolean, die ich hatte, ist als generischer Typparameter beim Erweitern generischer Klassen - eng verwandt mit Punkt 3.
Alex
6
Das Überladen des Konzepts von Null mit einer anderen Bedeutung als "Das Universum weiß es nicht" ist schwächer als die Verwendung einer Aufzählung mit 3 (oder mehr) Werten. Verdeutlicht auch das Lesen von Code, der Parameter an die Methode übergibt.
Bluevector
16
Oder # 4: Boolean isSchrodinger‎CatAlive = null;(Entschuldigung, konnte nicht widerstehen;)).
Matthieu
58

Ich benutze es fast nie, Booleanweil seine Semantik vage und dunkel ist. Grundsätzlich haben Sie eine 3-Zustands-Logik: wahr, falsch oder unbekannt. Manchmal ist es nützlich, es zu verwenden, wenn Sie dem Benutzer beispielsweise die Wahl zwischen zwei Werten gegeben haben und der Benutzer überhaupt nicht geantwortet hat und Sie diese Informationen wirklich wissen möchten (denken Sie an eine NULL-fähige Datenbankspalte).

Ich sehe keinen Grund für eine Konvertierung von booleannach, Booleanda dies zusätzlichen Speicheraufwand, NPE-Möglichkeit und weniger Typisierung mit sich bringt. Normalerweise benutze ich umständlich BooleanUtils.isTrue(), um mein Leben ein bisschen einfacher zu machen Boolean.

Der einzige Grund für die Existenz von Booleanist die Fähigkeit, Sammlungen von BooleanTyp zu haben (Generika erlauben nicht boolean, ebenso wie alle anderen Grundelemente).

Tomasz Nurkiewicz
quelle
1
Es ist jedoch eine externe Bibliothek (Apache Commons).
nhahtdh
4
Für mehrwertige Logik ist es vorzuziehen, Aufzählungen zu verwenden. Daher sollte Boolean für (Auto-) Boxvariablen zur Verwendung in Datenstrukturen belassen werden.
Jpe
39
Bei Verwendung von Boolean ist Boolean.TRUE.equals(myBooleanObject)oder ein praktischer Test zur Vermeidung von Nullzeigerausnahmen Boolean.FALSE.equals(myBooleanObject).
Christopher Peisert
10
Ein Boolesches Objekt hat nur zwei Zustände - trueund false. nullist kein Zustand des Objekts, sondern ein Zustand der Objektreferenz.
Hot Licks
2
Überlassen Sie es Apache Commons, zu sagen: "Jemand könnte es vermasseln, Boolesche Werte zu bewerten ... machen wir eine isTrue()Methode ...", was sich wie das dümmste verdammte Ding in der Geschichte der Utility-Funktionen anhört. Und doch ist es irgendwie nützlich ... das ist das größte WTF hier.
CorsiKa
33

Wow, was um alles in der Welt? Ist es nur ich oder sind all diese Antworten falsch oder zumindest irreführend?

Die Boolesche Klasse ist ein Wrapper um den booleschen Primitivtyp. Die Verwendung dieses Wrappers besteht darin, einen Booleschen Wert in einer Methode übergeben zu können, die ein Objekt oder eine generische Methode akzeptiert. Dh Vektor.

Ein Boolesches Objekt darf NIEMALS den Wert null haben. Wenn Ihr Verweis auf einen Booleschen Wert null ist, bedeutet dies einfach, dass Ihr Boolescher Wert nie erstellt wurde.

Dies könnte hilfreich sein: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Boolean.java

Eine boolesche Nullreferenz sollte nur verwendet werden, um eine ähnliche Logik auszulösen, für die Sie eine andere Nullreferenz haben. Die Verwendung für die Drei-Zustands-Logik ist umständlich.

EDIT: Beachten Sie, das Boolean a = true;ist eine irreführende Aussage. Dies entspricht wirklich etwas näherem. Boolean a = new Boolean(true); Siehe Autoboxing hier: http://en.wikipedia.org/wiki/Boxing_%28computer_science%29#Autoboxing

Vielleicht kommt hier ein Großteil der Verwirrung her.

EDIT2: Bitte lesen Sie die Kommentare unten. Wenn jemand eine Idee hat, wie ich meine Antwort umstrukturieren kann, um dies zu berücksichtigen, tun Sie dies bitte.

user606723
quelle
2
Ich verstehe Ihre Aussage "Ein Boolescher Wert kann NIEMALS den Wert null haben" nicht. Ich kann einen Boolean ( Boolean a = true;) erstellen und dann einen auf null ( a = null;) setzen. Es mag nicht elegant oder weise sein, aber es ist möglich.
Peter.murray.rust
7
Wenn du es tust Boolean a; a ist ein Zeiger auf ein Boolesches Objekt. Wenn Sie a = null;Ihren Booleschen Wert nicht auf null gesetzt haben, haben Sie Ihren Verweis auf null gesetzt. Haben Boolean a = null; a.booleanValue();in diesem Fall Sie nicht einmal erstellt ein Boolean - Objekt und daher wird es eine Nullpointer werfen. Lassen Sie mich wissen, wenn Sie weitere Anweisungen benötigen.
user606723
Wenn Sie dies tun Boolean a = true;, wird eine Art Magie ausgeführt, die tatsächlich als das interpretiert wird. Boolean a = new Boolean(true);Dies ist aus Leistungsgründen wahrscheinlich nicht vollständig korrekt, aber Sie müssen erkennen, dass der Boolesche Wert immer noch ein Objekt ist.
user606723
7
@missingno, Jeder Code, der sich mit einem Objekt befasst, muss sich damit befassen. Eine Objektreferenz kann entweder null sein oder nicht. Dies ist kein Sonderfall und erfordert keine besondere Berücksichtigung.
user606723
3
Du vermisst meinen Punkt @missingno. Ich bin damit einverstanden, dass wir Nullreferenzwerte berücksichtigen müssen. Ich habe nie dagegen gestritten. Aber wir müssen dies für JEDE OBJEKTREFERENZ tun . Eine Null-Boolesche Referenz ist kein Sonderfall. Daher erfordern null boolesche Referenzwerte keine besondere Berücksichtigung.
user606723
24

Es gibt drei schnelle Gründe:

  • um boolesche Werte der Datenbank darzustellen, die sein können true, falseodernull
  • um die xsd:booleanmit deklarierten Werte des XML-Schemas darzustellenxsd:nillable="true"
  • um generische Typen verwenden zu können: List<Boolean>- Sie können nicht verwendenList<boolean>
Grzegorz Grzybek
quelle
Ich habe explizit "boolean" geschrieben, nicht " boolean" (Mind Styling), weil Sie in Oracle normalerweise die char(1) nullWerte 'T' und 'F' verwenden. So kann es (mit zB Hibernate-Typ-Adapter) null sein :)
Grzegorz Grzybek
2
Welche Datenbank erlaubt keine Null für Boolesche Werte? Wenn Sie die Spalte auf null setzen, spielt der Datentyp keine Rolle mehr ...
Michal B.
@ MichaelB. Sybase (und SQL Server) Bit - Typ infocenter.sybase.com/help/index.jsp?topic=/...
mmmmmm
@ Mark - nein, SQL Server erlaubt ein nullbares Bit - msdn.microsoft.com/en-us/library/ms177603.aspx
David M
11

ANTWORT AUF EIGENE FRAGE: Ich dachte, es wäre nützlich, meine eigene Frage zu beantworten, da ich aus den Antworten viel gelernt habe. Diese Antwort soll denjenigen helfen - wie mir -, die die Probleme nicht vollständig verstehen. Wenn ich eine falsche Sprache verwende, korrigieren Sie mich bitte.

  • Der Nullwert ist kein Wert und unterscheidet sich grundlegend von trueund false. Es ist das Fehlen eines Zeigers auf Objekte. Daher ist es grundsätzlich falsch zu glauben, dass Boolean 3-wertig ist
  • Die Syntax für Boolean wird abgekürzt und verbirgt die Tatsache, dass die Referenz auf Objekte verweist:

    Boolean a = true;

verbirgt die Tatsache, dass truees sich um ein Objekt handelt. Andere äquivalente Aufgaben könnten sein:

Boolean a = Boolean.TRUE;

oder

Boolean a = new Boolean(true);
  • Die abgekürzte Syntax

    if (a) ...

unterscheidet sich von den meisten anderen Zuordnungen und verbirgt die Tatsache, dass a eine Objektreferenz oder ein Primitiv sein kann. Wenn es sich um ein Objekt handelt, muss es getestet werden null, um NPE zu vermeiden. Für mich ist es psychologisch einfacher, sich daran zu erinnern, wenn es einen Gleichheitstest gibt:

if (a == true) ...

wo wir möglicherweise aufgefordert werden, auf null zu testen. Die verkürzte Form ist also nur dann sicher, wenn aes sich um ein Grundelement handelt.

Für mich habe ich jetzt die Empfehlungen:

  • Verwenden Sie niemals Null für eine 3-wertige Logik. Verwenden Sie nur wahr und falsch.
  • Kehren Sie NIEMALS Booleanvon einer Methode zurück, wie sie sein könnte null. Nur zurück boolean.
  • Nur Booleanzum Umschließen von Elementen in Containern oder von Argumenten für Methoden, bei denen Objekte erforderlich sind
peter.murray.rust
quelle
5
Verwenden Sie nicht "new Boolean (was auch immer)". Dadurch wird ein neuer Boolescher Wert auf dem Heap instanziiert. Dennoch ist Boolean unveränderlich. Verwenden Sie "Boolean.valueOf (was auch immer)", um eine Referenz zu erstellen, die je nach was auch immer entweder auf Boolean.TRUE oder Boolean.False verweist.
simbo1905
1
Eines der vielen Probleme mit Java (IMHO nach 12 Jahren) ist die inkonsistente Herangehensweise an Nullwerte, die auch alte Sprachen haben. Bei einem Blick auf Scala gibt es das Konzept einer typisierten Option, die null sein oder einen Wert haben kann (Unterklassen Keine oder Einige). Dann können Sie myOption.getOrElse (defaultValue) aufrufen. Siehe scala-lang.org/api/current/scala/Option.html Diese Funktion ist nicht komplex. Da es jedoch in die neue JVM-Sprache integriert ist, wird es von vielen Bibliotheken verwendet. Das bewirkt, dass die Skalierung einige der Java-Probleme des "letzten Jahrhunderts" "behebt", aber dennoch in Klassendateien kompiliert wird, die auf der JRE ausgeführt werden.
simbo1905
10

Wrapper-Klassen für Grundelemente können verwendet werden, wenn Objekte erforderlich sind. Sammlungen sind ein gutes Beispiel.

Stellen Sie sich aus irgendeinem Grund Speicher eine Folge von müssen booleanin ein ArrayList, kann dies durch Boxen erfolgen booleanin Boolean.

Es gibt ein paar Worte über diese hier

Aus der Dokumentation:

Wie jeder Java-Programmierer weiß, können Sie kein int (oder einen anderen primitiven Wert) in eine Sammlung einfügen. Sammlungen können nur Objektreferenzen enthalten, daher müssen Sie primitive Werte in die entsprechende Wrapper-Klasse einfügen (im Fall von int Integer). Wenn Sie das Objekt aus der Sammlung entfernen, erhalten Sie die von Ihnen eingegebene Ganzzahl. Wenn Sie ein int benötigen, müssen Sie die Ganzzahl mit der intValue-Methode entpacken. All dieses Boxen und Unboxen ist ein Schmerz und bringt Ihren Code durcheinander. Die Autoboxing- und Unboxing-Funktion automatisiert den Prozess und beseitigt Schmerzen und Unordnung.

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

Francisco Spaeth
quelle
3

BooleanWrapper ist nützlich, wenn Sie möchten, ob neben trueund ein Wert zugewiesen wurde oder nicht false. Es hat die folgenden drei Zustände:

  • Wahr
  • Falsch
  • Nicht definiert was ist null

Während booleanhat nur zwei Staaten:

  • Wahr
  • Falsch

Der obige Unterschied macht es hilfreich in Wertelisten Boolean, die haben können True, Falseoder Null.

Ramesh PVK
quelle
Nein, es hat keinen Nullstatus, das ist die Referenz.
Matsemann
Was ich meinte war, dass Bolean für definiertes Richtig / Falsch und Nicht definiert verwendet werden kann.
Ramesh PVK
3

Ich nehme an, in einigen Fällen sollten Sie einen Mechanismus haben, um ein Boolesches Feld zu unterscheiden, das bereits einen Wert festgelegt hat oder nicht.

Thinhbk
quelle
1

Hauptzweck für Boolean ist der Nullwert. Der Nullwert besagt, dass die Eigenschaft undefiniert ist , z. B. eine nullbare Datenbankspalte.

Wenn Sie wirklich alles vom primitiven Booleschen in den Wrapper-Booleschen konvertieren müssen, können Sie Folgendes verwenden, um alten Code zu unterstützen:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...
JMelnik
quelle
6
'Der Hauptzweck ist der Nullwert'. Nein, der Hauptzweck von Boolean besteht darin, einen Verweis auf einen Boolean als Objekt zu übergeben.
user606723
@ user606723 stimmte zu, ich bezog mich beim Schreiben auf den Datenbankfall in meinem Kopf.
JMelnik
1

Es gibt viele Verwendungsmöglichkeiten für den Wert ** null ** im Booleschen Wrapper! :) :)

Beispielsweise können Sie in einem Formular ein Feld mit dem Namen "Newsletter" haben, das angibt, ob der Benutzer einen Newsletter von Ihrer Website möchte oder nicht. Wenn der Benutzer in diesem Feld keinen Wert auswählt, möchten Sie möglicherweise ein Standardverhalten für diese Situation implementieren (Senden? Nicht senden?, Frage erneut? Usw.). Nicht gesetzt (oder nicht ausgewählt oder ** null **) ist eindeutig nicht dasselbe wie wahr oder falsch.

Wenn "nicht gesetzt" jedoch nicht für Ihr Modell gilt, ändern Sie das boolesche Grundelement nicht;)

dcasanueva
quelle
1

In einer strengen Definition eines booleschen Elements gibt es nur zwei Werte. In einer perfekten Welt wäre das wahr. In der realen Welt kann das Element fehlen oder unbekannt sein. In der Regel handelt es sich dabei um Benutzereingaben. In einem bildschirmbasierten System kann dies durch eine Bearbeitung erzwungen werden. In einer Stapelwelt, die entweder eine Datenbank- oder eine XML-Eingabe verwendet, kann das Element leicht fehlen.

In der nicht perfekten Welt, in der wir leben, ist das Boolesche Objekt insofern großartig, als es den fehlenden oder unbekannten Zustand als Null darstellen kann. Schließlich modellieren Computer nur die reale Welt und sollten alle möglichen Zustände berücksichtigen und sie mit auslösenden Ausnahmen behandeln (meistens, da es Anwendungsfälle gibt, in denen das Auslösen der Ausnahme die richtige Antwort wäre).

In meinem Fall war das Boolesche Objekt die perfekte Antwort, da im Eingabe-XML manchmal das Element fehlte und ich immer noch einen Wert abrufen, ihn einem Booleschen Wert zuweisen und dann nach einer Null suchen konnte, bevor ich versuchte, einen wahren oder falschen Test damit zu verwenden .

Nur meine 2 Cent.

user3228876
quelle
1

Für all die guten Antworten oben werde ich nur ein konkretes Beispiel in der Java-Servlet- HttpSessionKlasse geben. Hoffe, dieses Beispiel hilft, einige Fragen zu klären, die Sie möglicherweise noch haben.

Wenn Sie Werte für eine Sitzung speichern und abrufen müssen, verwenden Sie die Methoden setAttribute(String, Object) und getAttribute(String, Object). Für einen booleschen Wert müssen Sie die boolesche Klasse verwenden, wenn Sie sie in einer http-Sitzung speichern möchten.

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

Die letzte Zeile verursacht a, NullPointerExceptionwenn die Attributwerte nicht festgelegt sind. (was der Grund ist, der mich zu diesem Beitrag geführt hat). Der logische Zustand 3 bleibt also bestehen, unabhängig davon, ob Sie ihn verwenden möchten oder nicht.

Wacker
quelle
0

Der beste Weg wäre, Boolesche Werte vollständig zu vermeiden, da jeder Boolesche Wert impliziert, dass Sie an einer anderen Stelle in Ihrem Code eine bedingte Anweisung haben (siehe http://www.antiifcampaign.com/ und diese Frage: Können Sie einen Algorithmus ohne eine if-Anweisung schreiben ? ? ).

Pragmatisch gesehen müssen Sie jedoch von Zeit zu Zeit Boolesche Werte verwenden. Wie Sie bereits selbst herausgefunden haben, ist der Umgang mit Booleschen Werten fehleranfälliger und umständlicher. Daher würde ich vorschlagen, wo immer möglich Boolesche Werte zu verwenden. Ausnahmen hiervon könnte eine Legacy-Datenbank mit nullbaren Booleschen Spalten sein, obwohl ich versuchen würde, dies auch in meiner Zuordnung zu verbergen.

Roland Schneider
quelle
Der Umgang mit Booleschen Werten ist genauso fehleranfällig wie der Umgang mit anderen Objekten. Übrigens ist der Link gegen die Verbreitung von IFs zur Typprüfung, nicht zur allgemeinen Verwendung. Und das ist wiederum "gefährlich", weil es Änderungen erschwert. An IFs an sich ist also nichts auszusetzen.
Mister Smith
Keine Antwort auf die Frage.
Matsemann
@MisterSmith Imho wird ein boolesches Flag häufig als Typprüfungsvariable missbraucht, sodass der Link auch hier gelten kann. Es sollte nur ein Hinweis sein, dass man darüber nachdenken sollte, ob ein Boolescher Wert in einer bestimmten Situation das richtige Werkzeug ist. Die Aussage "Boolesche Werte vollständig vermeiden" ist natürlich sehr radikal und praktisch unmöglich. Deshalb habe ich den zweiten Absatz hinzugefügt. Ich habe auch ein "fehleranfälligeres und umständlicheres" hinzugefügt, um die Dinge zu klären.
Roland Schneider
0

Boolean kann sehr hilfreich sein, wenn Sie drei Zustände benötigen. Wie beim Softwaretest, wenn der Test bestanden wurde, senden Sie true, wenn er fehlgeschlagen ist, senden Sie false und wenn der Testfall unterbrochen ist, senden Sie null, was bedeutet, dass der Testfall nicht ausgeführt wurde.

Aamir
quelle
2
Wären Enums nicht das Beste dafür? Im Gegensatz zu möglicherweise unerwarteten NullPointerExceptions für einen Client würden Aufzählungen explizit "Zustände" definieren
Kartik Chugh
Bevorzugen Sie in Zustandsautomaten immer Enums anstelle von Booleschen Werten. Sie wissen nie, wann ein neuer vierter Status in der Geschäftsanforderung eintrifft.
AnupamChugh