Warum erlaubt Autoboxing in Java mir 3 mögliche Werte für einen booleschen Wert?

7

Referenz: Ссылка

  

"Wenn Ihr Programm versucht, null zu autoungeben, wird eine NullPointerException ausgelöst."

javac gibt Ihnen einen Fehler bei der Kompilierung, wenn Sie versuchen, einem booleschen Wert null zuzuordnen. macht Sinn. das Zuweisen von null zu einem booleschen Wert ist jedoch a-ok. macht auch Sinn, schätze ich.

Aber lassen Sie uns darüber nachdenken, dass Sie eine NPE erhalten, wenn Sie versuchen, null zu autoun. Dies bedeutet, dass Sie Boolesche Operationen für Boolesche Operationen nicht ohne NULL-Prüfung oder Ausnahmeverarbeitung ausführen können. Gleiches gilt für mathematische Operationen an einem Integer.

Ich war lange Zeit ein Fan von Autoboxen in Java 1.5 +, weil ich dachte, dass Java näher dran ist, um wirklich objektorientiert zu sein. Aber nachdem ich letzte Nacht auf dieses Problem gestoßen bin, muss ich sagen, dass ich denke, dass es scheiße ist. Der Compiler, der mir einen Fehler gibt, wenn ich versuche, mit einem nicht initialisierten Primitiv zu arbeiten, ist eine gute Sache. Ich möchte Autoboxing nicht verwenden, wenn ich das verliere.

Ich denke, ich mag den Punkt des Autoboxierens falsch verstehen, aber gleichzeitig werde ich niemals akzeptieren, dass ein Boolescher Wert 3 Werte haben kann. Kann mir das jemand erklären? Was bekomme ich nicht?

    
John 27.05.2010, 17:11
quelle

9 Antworten

16

Boxed-Typen sind Referenztypen, und alle Referenztypen, primitive Boxen oder nicht, können sich auf null beziehen. Deshalb kann sich ein Boolean auf null beziehen. So kann ein Integer . So kann ein String , etc.

Boxed-Typen sind nicht dafür ausgelegt, Java wirklich objektorientiert zu machen. Java wird nie eine rein objektorientierte Sprache sein, und Sie sollten nicht so programmieren, als ob dies der Fall wäre. Primitive Typen werden niemals verschwinden und sollten in der Tat bevorzugt werden, wenn es eine Wahl gibt.

Hier ist ein Zitat von Effektive Java 2. Ausgabe, Eintrag 49: Primitive Typen primitiven Boxes vorziehen (Hervorhebung durch Autor):

  

Zusammenfassend können Sie primitive Elemente verwenden, die primitiven Boxed-Primitiven entsprechen, wenn Sie die Wahl haben. Primitive Typen sind einfacher und schneller. Wenn Sie Boxed-Primitive verwenden müssen, seien Sie vorsichtig! Autoboxing reduziert die Ausführlichkeit, aber nicht die Gefahr, Boxed-Primitive zu verwenden . Wenn Ihr Programm zwei Boxed-Primitive mit dem Operator == vergleicht, führt es einen Identitätsvergleich durch, der mit ziemlicher Sicherheit nicht ist, was Sie wollen. Wenn Ihr Programm gemischte Berechnungen mit Boxed- und Unboxed-Primitiven durchführt, wird das Unboxing ausgeführt und wenn Ihr Programm das Unboxing ausführt, kann es NullPointerException ausgeben. Schließlich, wenn Ihr Programm primitive Werte enthält, kann dies zu kostspieligen und unnötigen Objekt-Kreationen führen.

    
polygenelubricants 27.05.2010 17:21
quelle
7

Ich habe mindestens einen Fall gesehen, in dem der Wert null nützlich ist. Viele Datenobjekte in Webservices haben nullbare boolesche Felder. Manchmal vernachlässigt der Benutzer einen Wert. In diesem Fall möchten Sie das Fehlen eines Wertes von einem Standardwert erkennen können. Zuvor wurden Personen getX , setX und isXSet() Methoden schreiben, wobei isXSet false zurückgibt, bis jemand setX aufruft. Jetzt ist es möglich, X zu einem Nullwert-Typ zu machen und es ist klar, dass es nicht gesetzt wurde, wenn getX null zurückgibt.

    
jasonmp85 27.05.2010 17:28
quelle
5

Zusätzlich zu allem, was hier gesagt wird, gibt es Fälle, in denen Sie sehr gerne einen dritten Wert für boolesche Werte haben möchten - den Fall einer "optionalen" Eigenschaft.

Wir begegnen ihm normalerweise mit Datenbanken mit booleschen Spalten, die Nullen zulassen. Ohne boolesche Werte zu verwenden, müssten wir zwei separate Variablen verwenden, von denen die eine den Wert angibt und die andere, ob sie gültig ist.

Wenn Sie sich die JDBC-API ansehen, sehen Sie ein Beispiel für dieses Problem. Spalten erhalten einen Standardwert, wenn sie null sind (z. B. eine 0 für numerische Felder), und dann müssen Sie aufrufen " wasNull ", um zu prüfen, ob es sich um eine wahre 0 oder eine falsche Null handelt!

    
Uri 27.05.2010 17:24
quelle
4

Ihr Problem ist mit un Boxen, nicht Autoboxing. Ich denke, Auto-Boxen ist aus wichtigeren Gründen böse:

Bedenken Sie Folgendes:

%Vor%

One == hebt die Box auf und die andere nicht.

Unboxing auf Operatoren (im Gegensatz zu Zuweisungen) war meiner Ansicht nach ein Fehler (angesichts der oben genannten - es ist nur nicht Java). Boxen ist jedoch sehr schön.

    
Yishai 27.05.2010 17:31
quelle
1

Ich denke, es ist philosophischer als technische Frage. Wenn Sie den primitiven Typ in den Referenztyp umwandeln, sollten Sie bereit sein, dass Referenztypen (d. H. Objekte) nullfähig sind.

Sie können sich die The Billion Dollar Mistake Präsentation ansehen AUTO Hoare sagt, dass seine Einführung von Null auf oop (Algol 60) ein Fehler war.

Josh Bloch in Effective Java empfiehlt, primitive Typen zu bevorzugen, wo es möglich ist. Aber manchmal müssen Sie die boolesche Variable gegen Null verifizieren.

    
Roman 27.05.2010 17:21
quelle
0

Es gibt tatsächlich keinen großen Unterschied zu den Tagen vor Java 1.5 - das Problem ist nicht der boolesche Typ (er hat immer noch zwei Zustände), sondern der Boolesche Wrapper (der immer 3 Zustände hatte. Boolean.TRUE, Boolean.FALSE und null ).

Jede Konvertierung von einem booleschen Objekt in das boolesche Primitiv erfordert Null-Checks mit oder ohne Autoboxing.

    
Andreas_D 27.05.2010 17:22
quelle
0

Autoboxing transformiert automatisch Datentypen zwischen den intrinsischen Typen und Objekttypen.

Objekttypen für Boolean können Boolean.TRUE , Boolean.FALSE oder null sein. Deshalb müssen Sie mit den möglichen 3 Werten für einen booleschen Wert umgehen.

In Datenbanken ist es üblich, drei Zustände für einen booleschen Typ zu haben. Stellen Sie sich einen Datensatz vor, der nachverfolgt, ob jemand eine Klasse bestanden hat. Es gibt WAHR, für das Überholen; FALSE für nicht übergeben und NULL für "derzeit die Klasse nehmen". Ja, es ist seltsam, aber keinen Wert zu haben ist in objektorientierter Programmierung erben.

Ich finde auch das Autoboxing etwas abstoßend, hauptsächlich weil es ein Feature ist, bei dem der Compiler Bytecode hinzufügt, um den Konvertierungsprozess zu verarbeiten. Meiner Meinung nach kann dies dazu führen, dass die Leute wichtige Details im Umwandlungsprozess vergessen, die besser in Erinnerung bleiben (wie zum Beispiel das Null-Handling in Ihrem Fall). Es ist nützlich, aber nicht annähernd so nützlich wie die meisten anderen Funktionen der Java-Sprache.

Persönlich wünsche ich mir, dass die intrinsic als leichte Objekte anstelle von "eingebauten" Typen implementiert wurden. Es gibt viele Zeiten, in denen das hybride intrinsische / Objekttyp-System in die Quere kommt. Das heißt, intrinsics sollten da sein, um die Leistung zu verbessern, aber es scheint, dass, wenn Sie eine Menge intrinsisch zu Objekt-Marshalling tun müssen, Sie die intrinsic-only Leistungssteigerung nicht genießen können.

    
Edwin Buck 27.05.2010 17:20
quelle
0

Es ist das Problem mit dem Autoboxing, genau wie Integer i = null; . Integer -Objekt kann null sein, während ein natives int nicht sein kann.

    
fastcodejava 27.05.2010 17:31
quelle
0

Es wurde nie mit der Einführung von Autoboxen beabsichtigt, dass es die Primitiven ersetzt. In den meisten Orten sind Primitive was Sie wollen. Wenn Sie die Referenztypen verwenden möchten, weil "Java näher dran ist, um wirklich objektorientiert zu sein", dann ist das Ihr Aufruf, aber wie Sie feststellen, gibt es Nachteile bei diesem Ansatz. Leistung wird ein anderes Problem sein.

Autoboxing (und Auto-Boxing) hilft bei den Übergängen zwischen Code, der Primitive verwendet (die Mehrheit) und dem Code, der Referenztypen verwenden muss (selten). Von den Referenztypen ist Boolean zweifellos das seltenste, da es aufgrund seiner geringen Anzahl von Instanzen fast nie sinnvoll ist, eine Sammlung zu erstellen.

Zusammenfassend: Wenn die Referenztypen Probleme verursachen, verwenden Sie sie nicht. Aber sagen Sie nicht, dass Autoboxing schlecht ist, nur weil es sich herausgestellt hat, dass es in Ihrer Situation nicht hilfreich ist.

    
DJClayworth 27.05.2010 17:34
quelle