— Раз уж разработчики могли придумывать классы, которые описывают числа, они решили подойти к этому делу творчески, как настоящие разработчики.
Во-первых, придумали абстрактный класс Number (число), от которого унаследованы типы Byte, Short,Integer, Long, Float, Double. У него есть методы, которые помогают преобразовывать числа к другим числовым типам.
Методы класса Number | |
---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
— Действительно, ведь уже не напишешь:
Long x = 100000;
Integer y = (Integer) x;
— Ага. Типы то не примитивные. Поэтому используют методы класса Number:
Long x = 100000;
Integer y = x.intValue();
Но тут есть еще пара моментов. Т.к. Integer – это не int, то объекты такого типа нельзя сравнивать классическим знаком «==».
int x = 500;
int y = 500;
x == y; //true
Integer x = 500;
Integer y = 500;
x == y; //false
x.equals(y); //true
— Точно. Как-то я сразу об этом не подумал.
— Но и это еще не все.
— Господи, что же там еще-то?
— Когда мы присваиваем переменной типа Integer значение типа int, при этом вызывается метод Integer.valueOf:
Код | Что происходит на самом деле |
---|---|
|
|
— Ага. Я это понял еще примером выше.
— Так вот, функция valueOf не всегда создает новый объект типа Integer.
— Т.е. как это не всегда?
— Она кэширует значения от -128 до 127.
Код | Что происходит на самом деле | Описание |
---|---|---|
|
|
Все переменные x,y,z содержат ссылки на разные объекты |
|
|
Все переменные x,y,z содержат ссылки на один и тот же объект. |
|
|
Все переменные z,t содержат ссылки на один и тот же объект. |
Т.е. ситуация такая:
1) Если мы пишем new Integer(), то гарантированно создается новый объект.
2) Если мы вызываем Integer.valueOf(), явно или при autoboxing, то этот метод может вернуть для нас как новый объект, так и отдать объект из кэша, если переданное число лежит в диапазоне от -128 до 127.
— А что в этом такого страшного, если метод вернет объект из кэша?
— Да ничего. Просто нужно знать, что иногда, когда этого не ожидаешь, объекты могут быть равны. Там с равенством вообще все сложно. Если мы сравниваем примитивный тип и не примитивный, то они сравниваются как примитивы:
int x = 300;
Integer y = 300;
Integer z = 300;
x==y; //true (сравниваются как примитивы по значению)
x==z; //true (сравниваются как примитивы по значению)
y==z; //false (сравниваются по ссылке)
int x = 100;
Integer y = 100;
Integer z = 100;
x==y; //true (сравниваются как примитивы по значению)
x==z; //true (сравниваются как примитивы по значению)
y==z; //true (сравниваются по ссылке, ссылаются на один и тот же объект)
int x = 100;
Integer y = new Integer(100);
Integer z = 100;
x==y; //true (сравниваются как примитивы по значению)
x==z; //true (сравниваются как примитивы по значению)
y==z; //false (сравниваются по ссылке, ссылаются на различные объекты)
— М-да. И как все это запомнить…
— Не нужно это запоминать. Надо просто понять, как это все устроено и что происходит на самом деле, когда в дело вступает примитивный тип и его непримитивный аналог.
Еще советую тебе посмотреть на методы класса Integer, у него довольно много хороших и полезных методов. Ты даже одним из них часто пользовался.
— Ага. Помню. Integer.parseInt();