Warum ist 128 == 128 falsch, sondern 127 == 127 wahr ist, wenn Integer-Wrapper in Java zu vergleichen?
-
19-09-2019 - |
Frage
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
Ausgabe:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
Ausgabe:
true
Hinweis: Die Zahlen zwischen -128 und 127 sind true
.Lösung
Wenn Sie eine Nummer kompilieren wörtliche in Java und Zuweisen zu einem Integer (Kapital I
) der Compiler gibt:
Integer b2 =Integer.valueOf(127)
Diese Codezeile wird auch erzeugt, wenn Sie Autoboxing verwenden.
valueOf
ist so implementiert, dass bestimmte Zahlen „gepoolt“ werden, und es gibt die gleiche Instanz für Werte kleiner als 128.
Von dem Java-1.6-Quellcode, Zeile 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Der Wert von high
kann auf einem anderen Wert konfiguriert werden, mit der Systemeigenschaft.
-Djava.lang.Integer.IntegerCache.high = 999
Wenn Sie Ihr Programm mit der Systemeigenschaft laufen, gibt er wahr!
Die offensichtliche Schlussfolgerung: verlassen nie auf zwei Referenzen identisch sind, vergleichen sie immer mit .equals()
Methode
So b2.equals(b3)
für alle logisch gleichen Werte von b2 wahr drucken, b3.
Beachten Sie, dass Integer
Cache dort nicht aus Leistungsgründen, sondern vielmehr auf die JLS, Abschnitt 5.1.7 ; Objektidentität muss für Werte von -128 bis 127 einschließlich gegeben werden.
Integer # valueOf (int) auch dieses Verhalten dokumentiert:
Diese Methode ist wahrscheinlich durch Caching häufig geforderte Werte deutlich bessere Raum- und Zeitleistung erhalten. Diese Methode wird immer Cache-Werte im Bereich von -128 bis 127, und können andere Werte zwischenzuspeichern außerhalb dieses Bereichs.
Andere Tipps
Autoboxing-Caches -128 bis 127 in der JLS Dies ist angegeben ( 5.1.7 ).
Wenn der Wert p eingerahmt wird, ist wahr, falsch, ein Byte, ein Zeichen im Bereich \ u0000 bis \ u007f oder eine int oder Kurz Zahl zwischen -128 und 127, dann lassen Sie R1 und R2 werden die Ergebnisse von zwei Boxen Conversions p. Es ist immer der Fall, dass r 1 == r2.
Eine einfache Regel zu erinnern, wenn mit Objekten zu tun ist - Verwendung .equals
, wenn Sie, wenn die beiden Objekte prüfen wollen, „gleich“ sind, verwenden ==
wenn Sie sehen wollen, wenn sie auf die gleiche Instanz zeigen
Mit primitiven Datentypen, Ints, in beiden Fällen erzeugen würde wahr, die erwartete Ausgabe.
Da Sie Integer verwenden Objekte der Operator == eine andere Bedeutung hat.
Im Rahmen von Objekten, == prüft, ob die Variablen auf die gleiche Objekt Referenz beziehen.
Um den Wert der Objekte vergleichen Sie die Gleichen verwenden soll () -Methode Z.
b2.equals(b1)
, die zeigen an, ob b2 kleiner als b1, größer oder gleich (überprüfen Sie die API für weitere Details)
Es ist die Speicheroptimierung in Java zusammen.
auf Speicher zu speichern, Java ‚Wiederverwendungsmöglichkeiten‘ alle Wrapper-Objekte, deren Werte fallen in den folgenden Bereichen:
Alle Boolesche Werte (wahr und falsch)
Alle Byte-Werte
Alle Zeichen Werte von \ u0000 \ u007f (d.h. 0 bis 127 dezimal)
Alle Short und Integer-Werte von -128 bis 127.
Haben Sie einen Blick auf die Integer.java, wenn der Wert zwischen -128 und 127 ist, wird die im Cache-Pool nutzen, so (Integer) 1 == (Integer) 1
während (Integer) 222 != (Integer) 222
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Ich habe den folgenden wie dieses Problem nicht nur spezifisch für Integer ist. Meine Schlussfolgerung ist, dass mehr als oft nicht, wenn Sie die API nicht ordnungsgemäß verwenden, Schweller Sie falsches Verhalten sehen. Verwenden Sie es richtig, und Sie sollten das richtige Verhalten sehen:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}