„Ponieważ programiści mogli wymyślić klasy opisujące liczby, postanowili być kreatywni, jak prawdziwi programiści”.

„Najpierw wymyślili abstrakcyjną klasę Number, z której wywodzą się Byte, Short, Integer, Long, Float i Double. Posiada metody, które pomagają konwertować liczby na inne typy liczbowe”.

Metody klasy Number
1
int intValue()
2
long longValue()
3
float floatValue()
4
double doubleValue()
5
byte byteValue()
6
short shortValue()

„Racja. W końcu nie możesz tego napisać:”

Long x = 100000;
Integer y = (Integer) x;

„Tak, te typy nie są prymitywne. Dlatego używamy metod klasy Number:”

Long x = 100000;
Integer y = x.intValue();

„Ale wciąż jest kilka rzeczy do rozważenia. Ponieważ Integer nie jest typu int, obiektów typu Integer nie można porównywać z klasycznym operatorem «==»”.

Porównanie typów pierwotnych
int x = 500;
int y = 500;
x == y; //true
Porównanie typów nieprymitywnych
Integer x = 500;
Integer y = 500;
x == y; //false
x.equals(y); //true

"Dokładnie. Jakoś nie pomyślałem o tym od razu."

„Ale jest coś więcej”.

„Zwierasz moje obwody! Co jeszcze tam jest?”

„Kiedy przypisujemy wartość int do zmiennej Integer, wywoływana jest metoda Integer.valueOf:”

Kod Co naprawdę się dzieje
Integer x = 5;
Integer x = Integer.valueOf(5);

„Tak, już to zrozumiałem z powyższego przykładu”.

„Ale funkcja valueOf nie zawsze tworzy nowy obiekt typu Integer”.

„Uh, co masz na myśli mówiąc «nie zawsze»?”

„Pamiętuje wartości od -128 do 127”.

Kod Co naprawdę się dzieje Opis
Integer x = 300;
Integer y = 300;
Integer z = 300;
Integer x = Integer.valueOf(300);
Integer y = Integer.valueOf(300);
Integer z = Integer.valueOf(300);
Zmienne x, y i z zawierają odniesienia do różnych obiektów
Integer x = 100;
Integer y = 100;
Integer z = 100;
Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
Integer z = Integer.valueOf(100);
Zmienne x, y i z zawierają odniesienia do tego samego obiektu.
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = 10;
Integer t = 10;
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = Integer.valueOf(10);
Integer t = Integer.valueOf(10);
Zmienne z i t zawierają odniesienia do tego samego obiektu.

„Innymi słowy, sytuacja jest taka:”

1)  Jeśli napiszemy «new Integer()», mamy gwarancję otrzymania nowego obiektu.

2)  Jeśli wywołamy Integer.valueOf(), jawnie lub przez autoboxing, to metoda może zwrócić nowy obiekt lub obiekt z pamięci podręcznej, jeśli argument liczba mieści się w zakresie od -128 do 127.

„Co jest takiego strasznego w metodzie zwracającej obiekt z pamięci podręcznej?”

„Nieważne. Po prostu musisz wiedzieć, że czasami, kiedy się tego nie spodziewasz, przedmioty mogą być równe. Wszystko z równością jest skomplikowane. Jeśli porównamy prymityw z nie-prymitywem, wtedy zostaną porównane jako prymitywy:”

Kwestia porównania
int x = 300;
Integer y = 300;
Integer z = 300;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references)
Jeszcze ciekawszy przykład. Skrzynka wchodzi w obraz tutaj
int x = 100;
Integer y = 100;
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //true (comparison based on references; they point to the same object)
Ale pamięć podręczna nie jest tutaj zaangażowana
int x = 100;
Integer y = new Integer(100);
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references; they point to different objects)

„Świetnie… A jak ja to wszystko zapamiętam?”

„Nie musisz tego zapamiętywać. Musisz tylko zrozumieć, jak to wszystko jest zorganizowane i co właściwie się dzieje, gdy w grę wchodzą prymitywny i jego nieprymitywny odpowiednik”.

„Polecam też przyjrzeć się metodom klasy Integer. Ma ona całkiem sporo dobrych i użytecznych metod. Jedną z nich nawet często stosowałeś”.

„Tak, pamiętam. Integer.parseInt();”