
Ciężko na początku swojej nauki zrozumieć czemu porównywanie za pomocą operatora == jest nie do końca poprawne. Pytanie dotyczące porównywania Stringa na rozmowa rekrutacyjnych pojawia się równie często co pytanie o to czym jest interfejs.
Staramy wyrobić sobie taką intuicję, że o ile nie są to typy prymitywne (int, boolean..) to najlepszym rozwiązaniem będzie porównywanie obiektów za pomocą specjalnych metod – equals czy compareTo. Ale okazuje się, że czasami jednak to „naiwne” porównanie obiektów za pomocą operatora == działa i wtedy warto się zastanowić – czemu?
Sprawdźmy co siedzi w źródle
Zacznijmy może od przypomnienia, że konstrukcja:
Integer a = 128;
Jest przez kompilator konwertowana do:
Integer a = Integer.valueOf(128);
Jest to dosyć ważne, bo teraz wiemy gdzie szukać – zobaczmy co się kryje w metodzie valueOf:

Okazuje się, że valueOf robi coś więcej niż tylko opakowanie naszego inta w obiekt Integer. To też poniekąd tłumaczy sytuację, która widzimy tutaj:

Wracając do implementacji valueOf – jeżeli nasza wartość znajduje się w odpowiednim przedziale (domyślnie jest to: [-128, 127]) to zwrócona zostanie wartość z cache znajdującego się w statycznej klasie IntegerCache. Ten przedział możemy bez problemu zmienić ustawiając w konfiguracji VM zmienną -XX:AutoBoxCacheMax=rozmiar

Na zakończenie.. W jednym z projektów przy którym miałem okazję pracować jakiś czas temu, znalazłem sporo takich miejsc w których obiekty typu Integer porównywane są za pomocą ==. W momencie gdy poruszyłem ten temat, przedstawiając swoje obawy, dostałem odpowiedź – Przecież to działa, bo przy porównywaniu poprzez == jest unboxing. 🙂 I rzeczywiście to działało, ale powód był inny – te liczby, które zazwyczaj pod tymi zmiennymi się kryły, były po prostu bardzo małe.