Ich habe gerade einen ähnlichen Code gesehen:
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
}
}
Wenn dieser Codeblock ausgeführt wird, wird Folgendes ausgedruckt:
false
true
Ich verstehe, warum das erste ist false
: Weil die beiden Objekte getrennte Objekte sind, ==
vergleicht das die Referenzen. Aber ich kann nicht herausfinden, warum die zweite Aussage zurückkehrt true
. Gibt es eine seltsame Autoboxing-Regel, die aktiviert wird, wenn der Wert einer Ganzzahl in einem bestimmten Bereich liegt? Was ist denn hier los?
java
autoboxing
Joel
quelle
quelle
Antworten:
Die
true
Leitung wird tatsächlich durch die Sprachspezifikation garantiert. Aus Abschnitt 5.1.7 :Die Diskussion geht weiter und schlägt vor, dass Ihre zweite Ausgabezeile zwar garantiert ist, die erste jedoch nicht (siehe den letzten unten zitierten Absatz):
quelle
valueOf
Methode der Box-Klasse (wieInteger.valueOf(int)
) aufzurufen . Interessant, dass das JLS das genaue Unboxing-Desugaring definiert - unter Verwendung vonintValue()
et al. - aber nicht das Boxing-Desugaring.Integer
als über die offiziellepublic
API, dh das AufrufenintValue()
. Es gibt jedoch auch andere Möglichkeiten, eineInteger
Instanz für einenint
Wert abzurufen, z. B. kann ein Compiler Code generieren, der zuvor erstellteInteger
Instanzen beibehält und wiederverwendet .Ausgabe:
Ja, die erste Ausgabe wird zum Vergleichen der Referenz erzeugt. 'a' und 'b' - das sind zwei verschiedene Referenzen. In Punkt 1 werden tatsächlich zwei Referenzen erstellt, die ähnlich sind wie -
Die zweite Ausgabe wird erzeugt, weil
JVM
versucht wird, Speicher zu sparen, wenn dieInteger
in einen Bereich fällt (von -128 bis 127). Bei Punkt 2 wird für 'd' keine neue Referenz vom Typ Integer erstellt. Anstatt ein neues Objekt für die Referenzvariable vom Typ Integer 'd' zu erstellen, wird es nur dem zuvor erstellten Objekt zugewiesen, auf das mit 'c' verwiesen wird. All dies wird von erledigtJVM
.Diese Speicherregeln gelten nicht nur für Integer. Aus Gründen der Speicherersparnis sind zwei Instanzen der folgenden Wrapper-Objekte (während sie durch Boxen erstellt wurden) immer ==, wobei ihre primitiven Werte gleich sind -
\u007f
(7f ist 127 in Dezimalzahl)quelle
Long
hat auch Cache mit dem gleichen Bereich wieInteger
.Ganzzahlige Objekte in einem bestimmten Bereich (ich denke, vielleicht -128 bis 127) werden zwischengespeichert und wiederverwendet. Ganzzahlen außerhalb dieses Bereichs erhalten jedes Mal ein neues Objekt.
quelle
java.lang.Integer.IntegerCache.high
Eigenschaft erweitert werden . Interessant, dass Long diese Option nicht hat.Ja, es gibt eine seltsame Autoboxing-Regel, die aktiviert wird, wenn die Werte in einem bestimmten Bereich liegen. Wenn Sie einer Objektvariablen eine Konstante zuweisen, besagt nichts in der Sprachdefinition, dass ein neues Objekt erstellt werden muss . Möglicherweise wird ein vorhandenes Objekt aus dem Cache wiederverwendet.
Tatsächlich speichert die JVM zu diesem Zweck normalerweise einen Cache mit kleinen Ganzzahlen sowie Werte wie Boolean.TRUE und Boolean.FALSE.
quelle
Ich vermute, dass Java einen Cache mit kleinen Ganzzahlen verwaltet, die bereits "eingerahmt" sind, weil sie so häufig vorkommen, und es spart eine Menge Zeit, ein vorhandenes Objekt wiederzuverwenden, als ein neues zu erstellen.
quelle
Das ist ein interessanter Punkt. In dem Buch Effective Java wird empfohlen, immer Gleiches für Ihre eigenen Klassen zu überschreiben. Um die Gleichheit für zwei Objektinstanzen einer Java-Klasse zu überprüfen, verwenden Sie immer die Methode equals.
kehrt zurück:
quelle
In Java funktioniert das Boxen im Bereich zwischen -128 und 127 für eine Ganzzahl. Wenn Sie Zahlen in diesem Bereich verwenden, können Sie diese mit dem Operator == vergleichen. Für Integer-Objekte außerhalb des Bereichs müssen Sie equals verwenden.
quelle
Die direkte Zuweisung eines int-Literals zu einer Integer-Referenz ist ein Beispiel für das automatische Boxen, bei dem der Literalwert zum Objektkonvertierungscode vom Compiler verarbeitet wird.
Während der Kompilierungsphase konvertiert der Compiler
Integer a = 1000, b = 1000;
inInteger a = Integer.valueOf(1000), b = Integer.valueOf(1000);
.Es ist also die
Integer.valueOf()
Methode, die uns tatsächlich die Ganzzahlobjekte gibt, und wenn wir uns den Quellcode derInteger.valueOf()
Methode ansehen, können wir deutlich sehen, dass die Methode Ganzzahlobjekte im Bereich von -128 bis 127 (einschließlich) zwischenspeichert.Anstatt neue ganzzahlige Objekte zu erstellen und zurückzugeben, gibt
Integer.valueOf()
die Methode ganzzahlige Objekte aus dem internen zurück,IntegerCache
wenn das übergebene int-Literal größer als -128 und kleiner als 127 ist.Java speichert diese Ganzzahlobjekte zwischen, da dieser Bereich von Ganzzahlen in der täglichen Programmierung häufig verwendet wird, wodurch indirekt etwas Speicherplatz gespart wird.
Der Cache wird bei der ersten Verwendung initialisiert, wenn die Klasse aufgrund des statischen Blocks in den Speicher geladen wird. Der maximale Bereich des Caches kann über die
-XX:AutoBoxCacheMax
JVM-Option gesteuert werden .Dieses Caching - Verhalten ist nicht anwendbar für Integer nur Objekte, ähnlich wie Integer.IntegerCache haben wir auch
ByteCache, ShortCache, LongCache, CharacterCache
fürByte, Short, Long, Character
jeweils.Sie können mehr über meinen Artikel Java Integer Cache lesen - Warum Integer.valueOf (127) == Integer.valueOf (127) wahr ist .
quelle
In Java 5 wurde eine neue Funktion eingeführt, um Speicherplatz zu sparen und die Leistung für die Behandlung von Objekten vom Typ Integer zu verbessern. Ganzzahlige Objekte werden intern zwischengespeichert und über dieselben referenzierten Objekte wiederverwendet.
Dies gilt für Integer-Werte im Bereich zwischen –127 und +127 (Max Integer-Wert).
Dieses Integer-Caching funktioniert nur beim Autoboxing. Ganzzahlige Objekte werden nicht zwischengespeichert, wenn sie mit dem Konstruktor erstellt werden.
Für weitere Details gehen Sie bitte unter Link:
Ganzzahliger Cache im Detail
quelle
Wenn wir den Quellcode von
Integer
obeject überprüfen, finden wir die Quelle dervalueOf
Methode wie folgt :Dies kann erklären, warum
Integer
Objekte, die im Bereich von -128 (Integer.low
) bis 127 (Integer.high
) liegen, während des Autoboxing dieselben referenzierten Objekte sind. Und wir können sehen, dass es eine Klasse gibt,IntegerCache
die sich um dasInteger
Cache-Array kümmert , das eine private statische innere Klasse derInteger
Klasse ist.Es gibt ein weiteres interessantes Beispiel, das uns helfen kann, diese seltsame Situation zu verstehen:
quelle