1. Список типов-оберток

Все вы знаете, что в Java есть 8 примитивных типов, которые не являются классами. С одной стороны, это хорошо: они простые и занимают мало места, а с другой — иногда нужны именно классы. Зачем именно они, вы узнаете в следующей лекции.

Так что же делать?

Начиная с пятой версии, в Java у примитивных типов появились классы-близнецы. Каждый такой класс хранит внутри одно поле со значением определенного типа. Такие классы еще называют типами-обертками, потому что они как бы оборачивают примитивные значения в классы.

Вот список таких типов, ничего не узнаете?

Примитивный тип Класс-обертка
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
boolean
Boolean

Названия примитивных типов пишутся с маленькой буквы, а классов — с большой. Также названия классов немного длиннее: Integer вместо int и Character вместо char.

Все объекты классов-оберток являются неизменяемыми (immutable).

Упрощенный код класса Integer выглядит примерно так:

Код Примечание
public class Integer
{
   private int value;

   Integer(int x)
   {
      this.value = x;
   }

   public int intValue()
   {
      return this.value;
   }

   public static Integer valueOf(int x)
   {
      return new Integer(x);
   }
}


Переменная-значение

Конструктор




Метод возвращает значение




Статический метод создает новый объект Integer для переменной типа int

2. Преобразование типа int к Integer

Типы-обертки считаются аналогами их более примитивных собратьев: можно легко создать соответствующий объект-обертку для примитивного типа.

Разберем взаимодействие примитивных типов и их типов-оберток на примере типа int. Вот как бы выглядел код преобразования типа int к типу Integer и наоборот:

Чтобы преобразовать тип int к типу Integer, нужно написать код:

Integer имя = new Integer(значение);

Где имя — это имя переменной типа Integer, а значение — это оборачиваемое значение типа int.

Примеры:

Код Примечание
Integer age = new Integer(18);
Integer hundred = new Integer(100);
Integer zero = new Integer(0);

А чтобы преобразовать тип Integer к типу int, нужно написать код:

int имя = переменная.intValue();

Где имя — это имя переменной типа int, а переменная — это переменная-ссылка на объект типа Integer.

Примеры:

Код Примечание
Integer age = new Integer(18);
int x = age.intValue();

x == 18
Integer hundred = new Integer(100);
int y = hundred.intValue();

y == 100
Integer zero = new Integer(0);
int z = zero.intValue();


z == 0
int i = 110;
Integer zero = new Integer(i);
int z = zero.intValue();

z == 110


3. Autoboxing и unboxing

Однако даже простые операции с типом Integer писать непросто.

Как мы уже говорили, тип Integer — неизменяемый (immutable). Чтобы создать объект типа Integer с новым значением типа int, нужно явно создать новый объект Integer. Зато получить значение типа int, которое хранится внутри объекта Integer, просто: нужно вызвать метод intValue().

Пример:

Код Описание
Integer a = Integer.valueOf(5);
int b = a.intValue();
Integer c = new Integer(b + 5)
Оборачиваем 5 в класс Integer
Получаем значение из объекта Integer
Создаем новое значение Integer == 10

Код довольно громоздкий, не находите?

Создатели Java тоже так считают, поэтому они научили компилятор делать эти операции автоматически. Автоматическое преобразование int в Integer называется autoboxing (box — коробка, класть в коробку), а обратная операция — Integer к intunboxing.

Ваш код Что видит компилятор
Integer a = 10;
Integer a = Integer.valueOf(10);
int b = a;
int b = a.intValue();
Integer c = a + b;
Integer c = Integer.valueOf(a.intValue() + b);

Благодаря autoboxing и unboxing, вы можете спокойно присваивать тип int типу Integer и наоборот. Можно писать выражения любой сложности и не делать различий между типами int и Integer.

Примеры:

Код Что сгенерирует компилятор
Integer a = 5;
int b = a;
Integer c = a + b;
int d = a + b + c;
Integer a = Integer.valueOf(5);
int b = a.intValue();
Integer c = Integer.valueOf(a.intValue() + b);
int d = a.intValue() + b + c.intValue();
Integer a = 5;
int b = 5;

if (a == b)
{
   ...
}
Integer a = Integer.valueOf (5);
int b = 5;

if (a.intValue() == b)
{
   ...
}

4. Сравнение переменных классов-оберток

Autoboxing и unboxing работают очень просто и прозрачно: где нужно — расставляются команды new Integer(), где нужно — вызываются методы intValue().

Для вас как для программиста все работает легко и понятно. Но учтите, что если вы сравниваете Integer и Integer, происходит сравнение ссылок, а не значений.

Код Вывод на экран
Integer a = 1000;
Integer b = 1000;

System.out.println(a == b);



false
Integer a = 1000;
Integer b = 1000;

System.out.println(a.equals(b));



true

Переменные a и b хранят не значения (как типы int), а ссылки на объекты. Поэтому важно помнить, как правильно их сравнивать:

Неправильно Правильно
Integer a = 1000;
Integer b = 1000;
if (a == b)
{
   ...
}
Integer a = 1000;
Integer b = 1000;
if (a.equals(b))
{
   ...
}