Ciężko na początku swojej nauki zrozumieć czemu porównywanie dzięki 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ę, iż o ile nie są to typy prymitywne (int, boolean..) to najlepszym rozwiązaniem będzie porównywanie obiektów dzięki specjalnych metod – equals czy compareTo. Ale okazuje się, iż czasami jednak to „naiwne” porównanie obiektów dzięki operatora == działa i wtedy warto się zastanowić – czemu?
Sprawdźmy co siedzi w źródle
Zacznijmy może od przypomnienia, iż 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ę, iż 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 – o ile nasza wartość znajduje się we właściwym 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ą dzięki ==. 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 zwykle pod tymi zmiennymi się kryły, były po prostu bardzo małe.