sobota, marca 15, 2008

Ile to jest 1+1 w Java'ie?

Wydawało by się, że odpowiedź jest prosta...

Czy aby na pewno? ;-)
Spróbujmy sprawdzić jakiej odpowiedzi udzieli nam Java.

Użyjemy takiego kodu:

public class Integers {
public static void main(String[] args) throws Exception{
Integer i1 = 1;
Integer i2 = 1;
System.out.println(i1+"+"+i2+"="+(Integer)(i1+i2));
}
}

Jak łatwo się domyśleć ujrzymy na ekranie taki wynik:

1+1=2

A co gdy kod zmienimy w taki sposób jak poniżej?

import java.lang.reflect.Field;
public class Integers {
public static void main(String[] args) throws Exception {
Integer i1 = 1;
Integer i2 = 1;
System.out.println(i1+"+"+i2+"="+(Integer)(i1+i2));
fixIntegers();
System.out.println(i1+"+"+i2+"="+(Integer)(i1+i2));

}

static void fixIntegers() throws Exception {
Class integerClass = Integer.class;
Field value = integerClass.getDeclaredField("value");
value.setAccessible(true);
value.setInt(Integer.valueOf(2), 3);
}

}


Nagle ujrzymy taki oto wynik:
1+1=2
1+1=3

Dlaczego? ;-)

Sekret tkwi w 2 miejscach, pierwsze to metoda fixIntegers() która dokonuje niecnej podmiany wartości 2 na 3 dla obiektu typu Integer reprezentującego liczbę 2.
Drugie, nawet ważniejsze to pewna specyfika implementacji Sun'a. Wprowadzając auto- boxin i unboxing stwierdzono, że ze względu na optymalność wykorzystania pamięci i prędkości wykonywania kodu lepiej dla pewnej grupy obiektów typu Integer wprowadzić pewien mechanizm oszczędzający tak pamięć jak i takty procesora.
W końcu, po co za każdym razem gdy dokonuje się konwersja z typu int na Integer tworzyć całkiem nowy obiekt... szybciej i taniej będzie stworzyć pewien zestaw obiektów Integer trzymających wartości stosunkowo najczęściej potrzebne. I tak powstała sytuacja w której dla pewnego zakresu liczb w momencie konwersji na Integer'a zamiast konwersji jest podstawiany stały obiekt. Dla Sun Java [wersja 6 (build 1.6.0_03-b05), ale też dla Java 5] ten zestaw zaczyna się od liczby -128, a kończy na 127].
I w tym cały sekret ;-)


Podobne postybeta
Java 8 nadchodzi....
Sekrety klasy String ;-)
Giń konstruktorze! Giń! ;-)
Nieoczywiste oczywistości ;-) podstępny autoboxing ;-)
Sztuczki tropiciela błędów, part 3 - hackujemy klasy finalne ;-)

1 komentarz:

  1. Dorzucę swoje dwa grosze :) Jeśli chodzi o ten feature Integerów... to nie tylko Integer ma taki feature... polecam lekture Java Language Specification rozdział 5.1.7

    OdpowiedzUsuń