TL; DR
Java buforuje wystąpienia w postaci liczb całkowitych od -128
do 127
. Ponieważ używasz ==
do porównywania odwołań do obiektów zamiast wartości , będą pasować tylko obiekty z pamięci podręcznej. Możesz albo pracować z long
rozpakowanymi wartościami pierwotnymi, albo używać ich .equals()
do porównywania Long
obiektów.
Wersja długa (gra słów)
Dlaczego jest problem z porównaniem zmiennej Long z wartością większą niż 127? Jeśli typ danych powyższej zmiennej jest pierwotny (długi), kod działa dla wszystkich wartości.
Java buforuje instancje obiektów typu Integer z zakresu od -128 do 127 . To mówi:
- Jeśli ustawisz na N Long zmienne wartość
127
( buforowana ), ta sama instancja obiektu będzie wskazywana przez wszystkie odwołania. (N zmiennych, 1 instancja)
- Jeśli ustawisz wartość N Long zmiennych
128
( nie buforowaną ), będziesz mieć instancję obiektu wskazywaną przez każde odwołanie. (N zmiennych, N wystąpień)
Dlatego to:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Wyprowadza to:
prawda
fałsz
W przypadku wartości 127L , ponieważ oba odwołania (wart1 i wart2) wskazują na tę samą instancję obiektu w pamięci (w pamięci podręcznej), zwraca true
.
Z drugiej strony, dla wartości 128 , ponieważ nie ma dla niej instancji w pamięci podręcznej, tworzony jest nowy dla każdego nowego przypisania dla wartości w pudełku, co powoduje dwie różne instancje (wskazywane przez val3 i val4) i powraca false
do porównanie między nimi.
Dzieje się tak wyłącznie dlatego, że z operatorem porównujesz dwa Long
odwołania do obiektów , a nie long
wartości pierwotne ==
. Gdyby nie ten mechanizm pamięci podręcznej, te porównania zawsze kończyłyby się niepowodzeniem, więc prawdziwym problemem jest tutaj porównanie wartości pudełkowych z ==
operatorem.
Zmiana tych zmiennych na long
typy prymitywne zapobiegnie temu, ale w przypadku, gdy musisz zachować swój kod przy użyciu Long
obiektów, możesz bezpiecznie dokonać tych porównań, stosując następujące podejścia:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(Konieczne jest właściwe sprawdzenie zerowe, nawet w przypadku odlewów)
IMO , zawsze dobrze jest trzymać się metod .equals () podczas porównywania obiektów.
Linki referencyjne:
.longValue()
.Porównywanie innych niż prymitywy (aka Objects) w Javie z
==
porównuje ich odwołania zamiast ich wartości.Long
jest klasą i dlategoLong
wartości są obiektami.Problem polega na tym, że programiści Javy chcieli, aby ludzie używali
Long
ich tak, jak kiedyś,long
aby zapewnić kompatybilność, co doprowadziło do koncepcji autoboxingu, która jest zasadniczo cechą polegającą na tym, żelong
-wartości zostaną zmienione naLong
-Objects i odwrotnie w razie potrzeby. Zachowanie autoboxingu nie jest jednak przez cały czas dokładnie przewidywalne, ponieważ nie jest całkowicie określone.Aby być bezpiecznym i mieć przewidywalne wyniki, zawsze używaj
.equals()
do porównywania obiektów i nie polegaj w tym przypadku na autoboxingu:źródło