Ich weiß, dass, wenn Sie eine Boxed Primitive Integer mit einer Konstanten wie der folgenden vergleichen:
Integer a = 4;
if (a < 5)
a
wird automatisch entpackt und der Vergleich funktioniert.
Was passiert jedoch, wenn Sie zwei Boxen Integers
vergleichen und entweder Gleichheit oder weniger als / größer als vergleichen möchten?
Integer a = 4;
Integer b = 5;
if (a == b)
Wird der obige Code dazu führen, dass überprüft wird, ob es sich um dasselbe Objekt handelt, oder wird er in diesem Fall automatisch entpackt?
Wie wäre es mit:
Integer a = 4;
Integer b = 5;
if (a < b)
?
java
integer
autoboxing
shmosel
quelle
quelle
==
anstelle vonequals
das richtige Ergebnis liefert, kann dies daran liegen, dass die Zahlen in Kästchen interniert oder anderweitig wiederverwendet werden (vermutlich als Compiler-Optimierung). Der Grund, diese Frage zu stellen, besteht darin, herauszufinden, was intern geschieht und nicht, was anscheinend geschieht. (Zumindest bin ich deshalb hier.)Antworten:
Nein, == zwischen Integer, Long usw. prüft die Referenzgleichheit - dh
Dadurch wird geprüft, ob
x
undy
auf dasselbe Objekt und nicht auf gleiche Objekte verwiesen wird.So
wird garantiert gedruckt
false
. Das Internieren von "kleinen" Autoboxwerten kann zu schwierigen Ergebnissen führen:Dies wird
true
aufgrund der Regeln des Boxens gedruckt ( JLS Abschnitt 5.1.7 ). Es ist immer noch Gleichheit Referenz verwendet wird, aber die Referenzen echt sind gleich.Persönlich würde ich verwenden:
oder
Wie Sie sagen, für jeden Vergleich zwischen einem Wrapper - Typ (
Integer
,Long
usw.) und einem numerischen Typen (int
,long
usw.) der Wrapper Typwert ist unboxed und der Test auf die Grundwerte beteiligt angewendet wird.Dies erfolgt im Rahmen der binären numerischen Heraufstufung ( JLS-Abschnitt 5.6.2 ). Sehen Sie sich die Dokumentation jedes einzelnen Bedieners an, um festzustellen, ob sie angewendet wird. Zum Beispiel aus den Dokumenten für
==
und!=
( JLS 15.21.1 ):und für
<
,<=
,>
und>=
( JLS 15.20.1 )Beachten Sie, dass nichts davon als Teil der Situation betrachtet wird, in der keiner der Typen ein numerischer Typ ist.
quelle
x.compareTo(y) < 0
anstattx < y
?==
testet weiterhin die Objektgleichheit. Es ist jedoch leicht, sich täuschen zu lassen:Ihre Beispiele mit Ungleichungen funktionieren, da sie nicht für Objekte definiert sind. Beim
==
Vergleich wird jedoch weiterhin die Objektgleichheit überprüft. In diesem Fall wird beim Initialisieren der Objekte aus einem Boxed-Grundelement dasselbe Objekt verwendet (sowohl für a als auch für b). Dies ist eine gute Optimierung, da die primitiven Boxklassen unveränderlich sind.quelle
200
, werden beide Tests gedrucktfalse
.equals
Aufrufs" verstehen .Seit Java 1.7 können Sie Objects.equals verwenden :
quelle
==
prüft jedoch auf Referenzgleichheit, wenn Code geschrieben wird wie:Java ist klug genug, um dasselbe unveränderliche für
a
und wiederzuverwendenb
, also ist dies wahr :a == b
. Neugierig schrieb ich ein kleines Beispiel, um zu zeigen, wo Java auf diese Weise aufhört zu optimieren:Wenn ich dies kompiliere und ausführe (auf meinem Computer), erhalte ich:
quelle
tl; dr meine meinung ist es, eine unäre zu verwenden
+
die Unboxing auf einer der Operanden zu triggern , wenn für Wertgleichheit überprüft, und nur die Operatoren Mathematik anderweitig zu nutzen. Begründung folgt:Es wurde bereits erwähnt, dass der
==
Vergleich für einenInteger
Identitätsvergleich ist, was normalerweise nicht das ist, was ein Programmierer möchte, und dass das Ziel darin besteht, einen Wertevergleich durchzuführen. noch, ich habe ein wenig getan Wissenschaft darüber , wie dieser Vergleich zu tun , am effizientesten, sowohl in der Bezeichnung des Code Kompaktheit, Korrektheit und Geschwindigkeit.Ich habe die üblichen Methoden angewendet:
und habe diesen Code nach dem Kompilieren und Dekompilieren erhalten:
Wie Sie leicht sehen können, rufen Methode 1
Integer.equals()
(offensichtlich) auf, Methoden 2-4 führen zu genau demselben Code und entpacken die Werte mit.intValue()
und dann direktem Vergleich entpackt werden, und Methode 5 löst lediglich einen Identitätsvergleich aus, was der falsche Weg ist Werte vergleichen.Da (wie bereits von z. B. JS erwähnt)
equals()
ein Overhead entsteht (dies muss gescheheninstanceof
und eine ungeprüfte Umwandlung), arbeiten die Methoden 2 bis 4 mit genau der gleichen Geschwindigkeit, die in engen Schleifen deutlich besser ist als Methode 1, da HotSpot dies nicht ist wahrscheinlich die Casts & zu optimiereninstanceof
.Ähnlich verhält es sich mit anderen Vergleichsoperatoren (z. B.
<
/>
) - sie lösen Unboxing aus, während sie diescompareTo()
nicht tun -, aber diesmal ist die Operation von HS seitdem in hohem Maße optimierbarintValue()
es sich nur um eine Getter-Methode handelt (Hauptkandidat für eine Optimierung).Meiner Meinung nach ist die selten verwendete Version 4 die prägnanteste Methode - jeder erfahrene C / Java-Entwickler weiß, dass unäres Plus in den meisten Fällen gleichbedeutend mit
int
/ ist.intValue()
-, während es für einige (meistens für diejenigen, die dies nicht getan haben) ein kleiner WTF- Moment sein kann (verwenden Sie unary plus in ihrem Leben nicht), es zeigt wohl die Absicht am klarsten und am knappsten - es zeigt, dass wir einenint
Wert für einen der Operanden wollen, wodurch der andere Wert ebenfalls zum Entpacken gezwungen wird. Es ist auch dem reguläreni1 == i2
Vergleich, der für primitiveint
Werte verwendet wird, unbestreitbar am ähnlichsten .Meine Stimme gilt für
i1 == +i2
&i1 > i2
Stil fürInteger
Objekte, sowohl aus Gründen der Leistung als auch aus Gründen der Konsistenz. Außerdem kann der Code auf Grundelemente portiert werden, ohne dass etwas anderes als die Typdeklaration geändert werden muss. Die Verwendung benannter Methoden scheint mir semantisches Rauschen einzuführen, ähnlich dem viel kritisiertenbigInt.add(10).multiply(-3)
Stil.quelle
unary +
(unäres Plus), siehe z. B. stackoverflow.com/questions/2624410/…Berufung
Funktioniert die meiste Zeit, es ist jedoch nicht garantiert, dass es immer funktioniert. Verwenden Sie es daher nicht.
Der beste Weg, zwei Integer-Klassen auf Gleichheit zu vergleichen, vorausgesetzt, sie heißen 'a' und 'b', besteht darin, Folgendes aufzurufen:
Sie können auch diesen Weg verwenden, der etwas schneller ist.
Auf meinem Computer dauerten 99 Milliarden Vorgänge mit der ersten Methode 47 Sekunden und mit der zweiten Methode 46 Sekunden. Sie müssten Milliarden von Werten vergleichen, um einen Unterschied festzustellen.
Beachten Sie, dass 'a' möglicherweise null ist, da es sich um ein Objekt handelt. Ein Vergleich auf diese Weise führt nicht zu einer Nullzeigerausnahme.
Verwenden Sie zum Vergleichen von größer und kleiner als
quelle
if (a==b)
funktioniert nur für kleine Werte und funktioniert meistens nicht.Wir sollten immer die Methode equals () zum Vergleich für zwei ganze Zahlen wählen. Dies ist die empfohlene Vorgehensweise.
Wenn wir zwei Ganzzahlen mit == vergleichen, funktioniert dies aufgrund der internen Optimierung von JVM für einen bestimmten Bereich von Ganzzahlwerten (Ganzzahl von -128 bis 127).
Bitte sehen Sie Beispiele:
Fall 1:
Im obigen Fall verwendet JVM den Wert von a und b aus dem zwischengespeicherten Pool und gibt dieselbe Objektinstanz (daher Speicheradresse) des ganzzahligen Objekts zurück, und wir erhalten beide gleich. Es ist eine Optimierung, die JVM für bestimmte Bereichswerte durchführt.
Fall 2: In diesem Fall sind a und b nicht gleich, da sie nicht im Bereich von -128 bis 127 liegen.
Richtige Weg:
Ich hoffe das hilft.
quelle
In meinem Fall musste ich zwei
Integer
s für die Gleichheit vergleichen, wo beide sein konntennull
. Ähnliches Thema gesucht, nichts Elegantes dafür gefunden. Kam mit einem einfachen Dienstprogramm Funktionen.quelle
Weil die Vergleichsmethode basierend auf dem Typ int (x == y) oder der Klasse Integer (x.equals (y)) mit dem rechten Operator durchgeführt werden muss
quelle
Diese Methode vergleicht zwei Ganzzahlen mit der Nullprüfung, siehe Tests
quelle
Objects.equals(x,y)
Methode zu verwenden, als eine eigene zu rollen.