2010-05-27 13 views
7

Referenz: http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.htmlWarum erlaubt Autoboxing in Java mir 3 mögliche Werte für einen booleschen Wert?

"Wenn Ihr Programm versucht, null autounbox, wird es eine Nullpointer werfen."

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.

für eine lange Zeit war ich ein Fan von Autoboxing in Java 1.5 +, weil ich dachte, dass es Java näher zu sein, wirklich objektorientiert. 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?

+0

Eine Ja-oder-Nein-Frage kann drei Antworten haben: Ja, Nein, ich weiß es nicht – ADTC

Antwort

0

Autoboxing transformiert automatisch Datentypen zwischen 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, erbt in der objektorientierten Programmierung.

Ich finde auch Autoboxing ein wenig geschmacklos, vor allem, weil es ein Feature ist, wo der Compiler Bytecode hinzugefügt, um den Konvertierungsprozess zu behandeln. 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ünschte ich, dass die intrinsics 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 sollte 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.

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 entworfen, um Java wirklich objektorientiert zu machen. Java wird nie eine rein objektorientierte Sprache sein, und Sie sollten nicht Code als ob das der Fall ist. Primitive Typen werden niemals verschwinden und sollten in der Tat bevorzugt werden, wenn es eine Wahl gibt.

Hier ist ein Zitat aus Effective Java 2nd Edition, Punkt 49: Bevorzugen primitive Typen boxed Primitiven (Betonung durch Autor):

Zusammengefasst Verwendung Primitiven bevorzugt primitiv geboxt, wenn Sie das haben Wahl. 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 hoher Wahrscheinlichkeit 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 werfen. Schließlich, wenn Ihr Programm primitive Werte enthält, kann dies zu kostspieligen und unnötigen Objekt-Kreationen führen.

+0

Ist Das primäre Problem mit Autoboxing oder mit Auto-Unboxing? Es gibt einige Male, wenn Autoboxing problematisch sein kann (IMHO, wenn die Überladungsauflösung für eine N-Argument-Funktion ausgeführt wird, sollte Autoboxing für das Kth-Argument deaktiviert werden, wenn das Kth-Argument von * Jede * N-Argument-Überladung ist ein Primitiv), aber das automatische Unboxing scheint in den meisten Situationen gefährlich zu sein. – supercat

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 sehen The Billion Dollars Mistake Präsentation wo C.A.R. Hoare sagt, dass die Einführung von Null-Referenzen auf oop (Algol 60) ein Fehler war.

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

0

Es gibt eigentlich keinen großen Unterschied zu den Tagen vor Java 1.5 - das Problem ist nicht der boolesche Typ (es 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 Nullprüfungen mit oder ohne Autoboxing.

5

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

Wir begegnen es normalerweise mit Datenbanken, mit booleschen Spalten, die Nullen erlauben. Ohne Booleans 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, bei dem Spalten einen Standardwert erhalten, wenn sie Null sind (z. B. eine 0 für numerische Felder) und dann aufgerufen werden müssen "wasNull", um zu prüfen, ob es sich um eine wahre 0 oder eine falsche Null handelt!

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 würden Benutzer getX, setX und isXSet() Methoden schreiben, wobei isXSet false zurückgibt, bis jemand setX aufruft. Jetzt ist es möglich, X einen NULL-fähigen Typ zu machen und es ist klar, dass es nicht gesetzt wurde, wenn getXnull zurückgibt.

0

Es ist das Problem mit Autoboxing, genau wie Integer i = null;. Integer Objekt kann null sein, während eine native int nicht sein kann.

4

Ihr Problem ist mit Auto un Boxen, nicht Autoboxing. Ich denke, autounboxing für mehr gewichtige Gründe Übel ist:

diese Bedenken Sie:

Integer i = new Integer(1); 
Integer i2 = new Integer(12); 

System.out.println(i == 10 || i != i2); 

One == unboxes und der andere nicht.

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

0

Es war nie mit der Einführung von Autoboxing 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) ist da, um mit den Übergängen zwischen Code zu helfen, 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.

Zusammengefasst: Wenn die Referenztypen Probleme verursachen, verwenden Sie sie nicht. Aber sagen Sie nicht, dass Autoboxieren schlecht ist, nur weil sie sich in Ihrer Situation als nicht hilfreich erwiesen haben.

Verwandte Themen