2012-04-03 12 views
24

krocz ze mną ..porównywania wartości Integer w Javie, dziwne zachowanie

Integer x = 23; 
Integer y = 23; 

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

Podczas

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

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

Hmm ... Staram odlewania do int

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

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

Są one zarówno Liczby całkowite?

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 

Co wy myślicie? Co mogłoby wyjaśnić coś takiego?

+0

możliwe duplikat [Jak = operator i == operator pracuje w Javie ?] (http://stackoverflow.com/questions/9824053/how-operator-and-operator-works-in-java) – assylias

+0

Co robią 'getIndex();' i 'getSomeOtherIndex()'? –

+0

Prawdopodobny duplikat [Dlaczego 128 == 128 zwraca fałsz, ale 127 == 127 zwraca wartość true podczas konwersji do wrapperów Integer?] (Https://stackoverflow.com/questions/1700081/why-does-128-128-return- false-but-127-127-return-true-when-converting-to-integ) – Tom

Odpowiedz

42

Porównujesz wartości Integer, które są odniesieniami. Wymyślasz te odniesienia przez autoboxing. W przypadku niektórych wartości (gwarantowanych od -128 do 127) środowisko JRE przechowuje pamięć podręczną o obiektach Integer. Dla wyższych wartości nie. Od section 5.1.7 of the JLS:

Jeśli wartość p jest zapakowane jest prawdziwe, fałszywe, bajt, lub char w zakres \ u0000 do \ u007f lub int lub krótki numer pomiędzy -128 i 127 (włącznie), następnie niech r1 i r2 będą wynikami dowolnych dwóch konwersji bokserskich p. Zawsze jest tak, że r1 == r2.

Idealnie boksowanie danej prymitywnej wartości p zawsze dawało identyczne odniesienie. W praktyce może to nie być możliwe przy użyciu istniejących technik implementacji. Powyższe zasady są pragmatycznym kompromisem. Ostatnia klauzula powyżej wymaga, aby pewne wspólne wartości zawsze były zapakowane w nieodróżnialne obiekty. Implementacja może je buforować, leniwie lub niecierpliwie. W przypadku innych wartości formuła ta nie akceptuje żadnych założeń dotyczących tożsamości pudełkowych wartości w części programatora. Umożliwiłoby to (ale nie wymagało) współużytkowanie niektórych lub wszystkich tych odniesień.

Zapewnia to, że w większości przypadków zachowanie będzie pożądane, bez nakładania nadmiernej kary za wydajność, zwłaszcza na małych urządzeniach. Implementacje o mniejszej ilości pamięci mogą na przykład buforować wszystkie wartości char i short, a także wartości int i long w zakresie od -32K do + 32K.

Moralne: nie porównuj wartości Integer, jeśli interesują Cię podstawowe wartości int. Użyj wartości .equals() lub najpierw uzyskaj wartości int.

+2

@JAM: Tak, albo rzuć na 'int', wywołaj' intValue() 'i porównaj wyniki lub wywołaj' equals() '. –

+1

OK fajne; Dziękuję Jon! – JAM

1

Brzmi jak coś jest funky z auto-boxing, gdy używasz == na dwóch liczb całkowitych.

Zakładam, że działa poprawnie, gdy używasz Integer, jeśli używasz metody equals()? W każdym razie tak sądzę.

Nie używasz języka Java 1.4 lub czegoś w tym rodzaju?

+0

Inne odpowiedzi dokładnie wskazują, dlaczego tak się dzieje: JVM buforuje małe wartości liczb całkowitych. Tak więc, gdy porównasz (nowa liczba całkowita (12) == nowa liczba całkowita (12)) [daje true] JVM zwraca obiekt buforowany SAME dla obu stron o tej wartości równej 12. Rzeczywiście, obiekty są takie same. W przypadku dużych wartości tworzone są niezależnie nowe obiekty, a tak się nie dzieje. – ingyhere

13

Dla porównania liczb całkowitych prawidłowo, trzeba użyć .equals() lub porównać swoje pierwotne wartości, oddając do intintValue() lub dzwoniąc na nich.

Korzystanie == sprawdza, czy dwie liczby są samego obiektu, a nie, czy zawierają one samą wartość numeryczną.

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 

Zmieniano do zilustrowania punkt Jona z JLS o autoboxing:

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 

kontra:

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