piątek, 9 lipca 2010

Java Integer pool

Mam nadzieje, że nie jestem jednym z ostatnich, którzy się o tym dowiadują, ale kwestia tworzenia Integer'ów w Javie jest dość ciekawa. Prześledźmy kilka przykładów:
//1.
Integer i1 = 12345
Integer i2 = 12345
//(i1==i2) -> false

//2.
Integer i1 = 127
Integer i2 = 127
//(i1==i2) -> true

//3.
Integer i1 = new Integer(127)
Integer i2 = new Integer(127)
//(i1==i2) -> false

A teraz komentarz:
1. Takie przypisanie zmiennej prymitywnej w starszej wersji Javy było w ogóle nie możliwe. Teraz jednak rusza do akcji "opakowywacz" i z typu prymitywnego int robi Integer, dzięki temu obie instrukcje przypisania są poprawne. Porównanie i1==i2 odnosi się oczywiście do referencji. Referencje wskazują na osobne obiekty, dlatego porównanie zwraca wartość false.

2. Tu jest ciekawiej. Dlaczego odwołując się do tego co napisałem powyżej, w tym przypadku jest inaczej? Otóż Java, obiekty typu Integer (również Byte, Short, Long) o wartościach od -128 do 127, przechowuje w specjalnej puli, gdzie obiekty te po prostu nie powtarzają się. Dlatego też referencje wskazują na ten sam obiekt w puli.

3. W ostatnim przykładzie wymuszamy (przez new) otworzenie 2 osobnych obiektów. Stąd wartość porównania wynosi znowu false (niezależnie już od wartości).

2 komentarze:

  1. @2: tutaj warto podkreślić że nie koniecznie jest to zakres -128-127, i nie należy zakładać że na każdym JVM tak będzie.

    OdpowiedzUsuń
  2. dla liczb z zakresu -128..127 mozna polegac na takim zachowaniu, specyfikacja to gwarantuje http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#190730

    Ale faktycznie moze on byc szerszy na danej JVM

    OdpowiedzUsuń