Począwszy od Javy 1.5, można Integer
z niej korzystać int
w wielu sytuacjach.
Jednak znalazłem potencjalną wadę w moim kodzie, która trochę mnie zaskoczyła.
Poniższy kod:
Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
mismatch = true;
wydawało się, że ustawienie niezgodności jest nieprawidłowe, gdy wartości były równe, chociaż nie mogę określić, w jakich okolicznościach. Ustawiłem punkt przerwania w Eclipse i zobaczyłem, że Integer
wartości były równe 137, i sprawdziłem wyrażenie logiczne i stwierdziłem, że jest fałszywe, ale kiedy go przekroczyłem, ustawiało niezgodność na true.
Zmiana warunku na:
if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))
naprawiono problem.
Czy ktoś może rzucić trochę światła na to, dlaczego tak się stało? Jak dotąd widziałem zachowanie tylko na moim hoście lokalnym na moim własnym komputerze. W tym konkretnym przypadku kod z powodzeniem pokonał około 20 porównań, ale zawiódł na 2. Problem był powtarzalny.
Jeśli jest to powszechny problem, powinien powodować błędy w innych naszych środowiskach (deweloperskich i testowych), ale jak dotąd nikt nie zgłosił problemu po setkach testów wykonujących ten fragment kodu.
Czy nadal nie jest to zgodne z prawem ==
porównywanie dwóch Integer
wartości?
Oprócz wszystkich dobrych odpowiedzi poniżej, poniższy link stackoverflow zawiera sporo dodatkowych informacji. Właściwie odpowiedziałby na moje pierwotne pytanie, ale ponieważ nie wspomniałem w moim pytaniu o autoboxingu, nie pojawił się w wybranych sugestiach:
Dlaczego kompilator / JVM nie może po prostu sprawić, by autoboxing „po prostu działał”?
Nie możesz porównać dwóch
Integer
z prostymi==
obiektami to, więc przez większość czasu odniesienia nie będą takie same.Istnieje sztuczka,
Integer
między -128 a 127 referencje będą takie same, jak w przypadku autoboxingu,Integer.valueOf()
który buforuje małe liczby całkowite.Zasoby :
Na ten sam temat:
źródło
new Integer(1) == new Integer(1)
jest nadal fałszywa.new ... == new ...
jest zawszefalse
.equals()
przypadku obiektów. Powinna to być jedna z pierwszych rzeczy, które należy wiedzieć podczas nauki języka Java. Nawiasem mówiąc, domyśliłbym się, że konstruktorInteger
był prywatny, tj. Że instancje zawsze były tworzone za pomocąvalueOf()
metody. Ale widzę, że konstruktor jest publiczny.Problem polega na tym, że twoje dwa obiekty typu Integer są po prostu obiektami. Nie pasują, ponieważ porównujesz dwa odwołania do obiektów, a nie wartości w nich zawarte. Oczywiście
.equals
jest zastępowany, aby zapewnić porównanie wartości, a nie porównanie odniesień do obiektów.źródło
Integer
odnosi się do odniesienia, to znaczy podczas porównywania odniesień, które porównujesz, jeśli wskazują na ten sam obiekt, a nie wartość. Stąd problem, który widzisz. Powodem, dla którego działa tak dobrze zint
typami zwykłymi, jest to, że rozpakowuje wartość zawartą wInteger
.Mogę dodać, że jeśli robisz to, co robisz, to po co miałbyś
if
zacząć od stwierdzenia?źródło
„==” zawsze porównuje lokalizację pamięci lub odniesienia do obiektów wartości. equals zawsze porównuje wartości. Ale equals pośrednio używa operatora „==” do porównywania wartości.
Integer używa pamięci podręcznej Integer do przechowywania wartości od -128 do +127. Jeśli operator == jest używany do sprawdzania wartości od -128 do 127, zwraca prawdę. dla innych niż te wartości zwraca false.
Skorzystaj z łącza, aby uzyskać dodatkowe informacje
źródło
Aby uzyskać poprawność użycia
==
, możesz po prostu rozpakować jedną z porównywanychInteger
wartości przed wykonaniem==
porównania, na przykład:Drugi zostanie automatycznie rozpakowany (oczywiście musisz
null
najpierw sprawdzić ).źródło
Oprócz tych wspaniałych odpowiedzi, dowiedziałem się, że:
źródło