Inkonsistentes Verhalten bei Javas ==
Frage
Betrachten Sie diesen Code:
class test {
public static void main(String[] args) {
test inst_test = new test();
int i1 = 2000;
int i2 = 2000;
int i3 = 2;
int i4 = 2;
Integer Ithree = new Integer(2); // 1
Integer Ifour = new Integer(2); // 2
System.out.println( Ithree == Ifour );
inst_test.method( i3 , i4 );
inst_test.method( i1 , i2 );
}
public void method( Integer i , Integer eye ) {
System.out.println(i == eye );
}
}
Es druckt:
false
true
false
Ich verstehe den ersten false
, Der == Operator prüft nur, ob zwei Referenzen an demselben Objekt funktionieren, was in diesem Fall nicht der Fall ist.
Folgende true
und false
Lass mich meinen Kopf kratzen. Warum sollte Java in Betracht ziehen? i3
und i4
gleich aber i1
und i2
anders? Beide wurden an Ganzzahl gewickelt, sollte nicht beide zu falsch bewerten? Gibt es einen praktischen Grund für diese Inkonsistenz?
Lösung
Autoboxierung von Primitiven in Objekte (wie in Ihren Aufrufen an verwendet method
Verwendet einen Cache mit kleinen Werten. Von dem Java -Sprachspezifikation Abschnitt 5.1.7:
Wenn der Wert P, der gepackt wird, ist wahr, falsch, ein Byte, ein Zeichen im Bereich u0000 bis u007f oder eine int oder eine Kurznummer zwischen -128 und 127, dann sei R1 und R2 die Ergebnisse von zwei Box -Konvertierungen, von p. Es ist immer der Fall, dass R1 == R2.
Der Diskussionsteil der Spezifikation unmittelbar auch ist interessant. Bemerkenswerterweise kann ein JVM -Cache Cache mehr Werte, wenn es will - Sie können sich nicht sicher sein, dass die Ergebnisse von Tun:
Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
Andere Tipps
Beim Autoboxen werden Ganzzahlen zwischen -128 und 127 zwischengespeichert und das gleiche Wrapper -Objekt wird zurückgegeben. Das Gleiche gilt für boolesche Werte und Zeichenwerte zwischen u0000 und u007f
Dies ist das, was Sie die meiste Zeit erhalten, es hängt jedoch von der JVM -Implementierung ab.
Dies liegt daran, dass Boxen Ganzzahlen unter einem bestimmten Wert (128, glaube ich) auf ein vorkonstruiertes Objekt und höhere Werte auf neue Objekte beziehen.
Autoboxen verwendet Integer.Valueof (i), nicht neue Ganzzahl (i), um ein Objekt der Klassengülle zu konstruieren.
Wie die anderen gesagt haben, verwendet ValueOf () einen Cache, hauptsächlich für Platzeffizienz.
Verwenden Sie nicht == bei Referenztypen, es ist fast immer ein Fehler.
Die Ganzzahlklasse enthält einen Cache einiger häufig verwendeter Instanzen. Der Wertebereich variiert im Allgemeinen von JVM bis JVM (manchmal auch konfigurierbar), aber im Allgemeinen ist der entsprechende Code etwas wie:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
(Code von Sun Jdk 1.6)
Dies ist wie ein Schnitt für String, da beide Speicher Speicher speichern und die Gleichheit mit einer Referenz (z. == anstelle von gleich)
Ich würde vermuten, dass die Verpackung versucht, die Anzahl der Ganzzahlobjekte zu minimieren, und nur ein Objekt erstellt, das 2 darstellt, und den Speicher zu speichern.
Denken Sie nur daran, niemals == für Objekte zu verwenden, von denen Sie nie wissen, was passiert.
Autoboxing Verwenden Sie einen Caching -Mechanismus. Normalerweise solltest du dich niemals verlassen ==
, Verwenden Sie immer equals
Gleichheit überprüfen.