2012-04-03 12 views
24

Walk with me ..Vergleich Integer-Werte in Java, seltsame Verhalten

Integer x = 23; 
Integer y = 23; 

if (x == y) 
    System.out.println("what else");  // All is well as expected 
else 
    System.out.println("..."); 

Während

Integer x = someObject.getIndex(); 
Integer y = someOtherObject.getSomeOtherIndex(); 

if (x == y) 
    System.out.println("what else"); 
else 
    System.out.println("...");  // Prints this 

Hmm ... Ich versuche

int x = someObject.getIndex(); 
int y = someOtherObject.getSomeOtherIndex() 

if (x == y)  
    System.out.println("what else"); // works fine 
else 
    System.out.println("..."); 

int Gießen Sind sie beide Ganzzahlen?

System.out.println(x.getClass().getName());    // java.lang.Integer 
System.out.println(y.getClass().getName());    // java.lang.Integer 
System.out.println(someObject.getIndex());    // java.lang.Integer 
System.out.println(someOtherObject.getSomeOtherIndex()); // java.lang.Integer 

Was denkst du? Was würde so etwas erklären?

+0

möglich Duplikat von [Wie Operator = und == Operator arbeitet in Java ?] (http://stackoverflow.com/questions/9824053/how-operator-and-operator-works-in-java) – assylias

+0

Was tun 'getIndex();' und 'getSomeOtherIndex()'? –

+0

Mögliches Duplikat von [Warum gibt 128 == 128 false zurück, 127 == 127 gibt true zurück, wenn in Integer-Wrapper konvertiert wird?] (Https://stackoverflow.com/questions/1700081/why-does-128-128-return- false-but-127-127-return-true-wenn-converting-to-integ) – Tom

Antwort

42

Sie vergleichen Integer Werte, die Referenzen sind. Sie kommen mit diesen Referenzen über Autoboxing. Für einige Werte (garantiert für -128 bis 127) verwaltet die JRE einen Cache von Integer Objekten. Für höhere Werte gilt dies nicht. Von section 5.1.7 of the JLS:

Wenn der Wert p eingerahmt wird, ist wahr, falsch, ein Byte oder ein Zeichen im Bereich \ u0000 bis \ u007f oder eine int oder Kurz Zahl zwischen -128 und 127 (einschließlich), dann seien r1 und r2 die Ergebnisse von zwei Box-Umwandlungen von p. Es ist immer der Fall, dass r1 == r2.

Im Idealfall würde das Boxen eines gegebenen Grundwerts p immer eine identische Referenz ergeben. In der Praxis ist dies unter Verwendung bestehender Implementierungstechniken möglicherweise nicht durchführbar. Die obigen Regeln sind ein pragmatischer Kompromiss. Der letzte Abschnitt erfordert, dass bestimmte gemeinsame Werte immer in nicht unterscheidbare Objekte eingereiht werden. Die Implementierung kann diese faul oder eifrig zwischenspeichern. Für andere Werte lässt diese Formulierung keine Annahmen über die Identität der eingepackten Werte auf Seiten des Programmierers zu. Dies würde es ermöglichen (aber nicht erfordern), einige oder alle dieser Referenzen zu teilen.

Dies stellt sicher, dass das Verhalten in den meisten Fällen das gewünschte ist, ohne dass dies zu einer übermäßigen Leistungseinbuße führt, insbesondere bei kleinen Geräten. Weniger speicherbeschränkte Implementierungen können beispielsweise alle char- und short-Werte sowie int- und long-Werte im Bereich von -32K bis + 32K zwischenspeichern.

Moral: nicht vergleichen Integer Referenzen, wenn Sie in den zugrundeliegenden int Werte interessiert sind. Verwenden Sie .equals() oder rufen Sie zuerst die Werte int ab.

+2

@JAM: Ja, entweder auf "int" umwandeln, 'intValue()' aufrufen und die Ergebnisse vergleichen oder 'equals() aufrufen '. –

+1

Ok cool; Danke Jon! – JAM

1

Klingt wie etwas ist funky mit Auto-Boxen, wenn Sie == auf den beiden Ganzzahlen verwenden.

Ich würde davon ausgehen, dass es funktioniert, wenn Sie Integer verwenden, wenn Sie die equals() Methode verwenden? Das würde ich sowieso vermuten.

Sie verwenden nicht Java 1.4 oder etwas sind Sie?

+0

Die anderen Antworten zeigen genau, warum dies geschieht: Die JVM speichert kleine Werte von Ganzzahlen. Wenn ich also vergleiche (new Integer (12) == new Integer (12)) [ergibt true], gibt die JVM das zwischengespeicherte Objekt SAME für beide Seiten dieses Wertes von 12 zurück. Die Objekte sind also tatsächlich gleich. Bei großen Werten werden unabhängig voneinander neue Objekte erstellt, und dies geschieht nicht. – ingyhere

13

Um die Ganzzahlen richtig zu vergleichen, müssen Sie .equals() verwenden oder ihre Grundwerte vergleichen, indem Sie sie an int oder intValue() umwandeln.

Mit == überprüft, ob die beiden ganzen Zahlen sind die gleiche Objekt, nicht, ob sie die gleichen numerischen Wert enthalten.

Integer a = new Integer(1); 
    Integer b = new Integer(1); 

    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false 

Herausgegeben Jons Punkt von der JLS über Autoboxing zu illustrieren:

Integer a = 1; 
    Integer b = 1; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //true 

gegen:

Integer a = 128; 
    Integer b = 128; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false