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))
{
   ...
}