Dlaczego 128 = = 128 jest fałszywe, ale 127= = 127 jest prawdziwe podczas porównywania wrapperów całkowitych w Javie?

class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

Wyjście:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

Wyjście:

true

Uwaga: liczby od -128 do 127 są prawdziwe.

Author: Steve Chambers, 2009-11-09

6 answers

Kiedy kompilujesz liczbę literał w Javie i przypisujesz ją do liczby całkowitej (capital I) kompilator emituje:

Integer b2 =Integer.valueOf(127)

Ta linia kodu jest również generowana podczas korzystania z autoboxingu.

valueOf jest zaimplementowana w taki sposób, że pewne liczby są "łączone" i zwraca tę samą instancję dla wartości mniejszych niż 128.

Z kodu źródłowego Javy 1.6, linia 621:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

Wartość high może być ustawiona na inną wartość, z właściwością systemową.

-Djava.lang.Liczba całkowita.IntegerCache.high = 999

Jeśli uruchomisz swój program z tą właściwością systemową, wyświetli się true!

Oczywisty wniosek: nigdy nie polegaj na tym, że dwa odniesienia są identyczne, zawsze porównuj je z metodą .equals().

Więc b2.equals(b3) wyświetli true dla wszystkich logicznie równych wartości b2,b3.

Zauważ, że Integer cache nie jest tam ze względu na wydajność, ale raczej do połączenia z JLS, sekcja 5.1.7; tożsamość obiektu musi być podana dla wartości -128 do 127 włącznie.

Integer # valueOf (int) również dokumentuje to zachowanie:

Ta metoda może przynieść znacznie lepszą wydajność przestrzeni i czasu poprzez buforowanie często żądanych wartości. Ta metoda zawsze buforuje wartości z zakresu -128 do 127, włącznie, i może buforować inne wartości spoza tego zakresu.

 182
Author: Andreas Petersson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-16 15:29:24

Autoboxing Cache -128 do 127. Jest to określone w JLS (5.1.7).

Jeśli wartość p jest ustawiona w polu true, false, bajt, znak w zakresie od \u0000 do \u007f, lub liczba int lub krótka pomiędzy -128 i 127, niech r1 i r2 będą wynikami dowolnych dwóch przeliczników boksu P. zawsze jest tak, że r1 == r2.

Prostą regułą do zapamiętania przy obsłudze obiektów jest-use .równa się, jeśli chcesz sprawdzić, czy dwa obiekty są "równe", użyj==, gdy chcesz sprawdzić, czy wskazują na tę samą instancję.

 20
Author: Michael Lloyd Lee mlk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-25 08:59:32

Użycie prymitywnych typów danych, ints, wytworzyłoby true w obu przypadkach oczekiwane wyjście.

Jednakże, ponieważ używasz obiektów całkowitych, operator = = ma inne znaczenie.

W kontekście obiektów = = sprawdza, czy zmienne odnoszą się do tego samego obiektu.

Aby porównać wartość obiektów należy użyć metody equals() Np.

 b2.equals(b1)

Który wskaże, czy b2 jest mniejszy niż b1, większy lub równy (sprawdź API dla szczegóły)

 8
Author: chrisbunney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 10:09:09

Jest to optymalizacja pamięci w Javie.

Aby zapisać w pamięci, Java "wykorzystuje" wszystkie obiekty wrappera, których wartości spadek w następujących zakresach:

Wszystkie wartości logiczne (true I false)

Wszystkie wartości bajtów

Wszystkie wartości znaków od \u0000 do \u007f (tj. od 0 do 127 w układzie dziesiętnym)

Wszystkie krótkie i całkowite wartości od -128 do 127.

Uwaga:

  • Jeśli utworzysz Boolean z new Boolean (value); zawsze otrzymasz nowy obiekt

  • Jeśli utworzysz łańcuch z nowym łańcuchem (wartością); zawsze otrzymasz nowy obiekt

  • Jeśli utworzysz liczbę całkowitą z nową liczbą całkowitą (wartość); zawsze otrzymasz nowy obiekt

Itd.

 4
Author: Willmore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 08:03:01

Spójrz na liczbę całkowitą.java, jeśli wartość mieści się w przedziale od -128 do 127, użyje buforowanej puli, więc (Integer) 1 == (Integer) 1 while (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);
}       
 2
Author: yanghaogn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-16 02:05:28

Napisałem co następuje, ponieważ ten problem nie jest tylko specyficzny dla Integer. Mój wniosek jest taki, że częściej, jeśli używasz API nieprawidłowo, widzisz nieprawidłowe zachowanie. Użyj go poprawnie i powinieneś zobaczyć prawidłowe zachowanie:

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

}
 -4
Author: thejartender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-11 08:50:33