- Совместимость и единообразие
- null
- Утилиты и значения
- Почему так устроено?
- Боксинг и анбоксинг (Boxing and Unboxing)
В Java у каждого примитивного типа есть соответствующий "объектный" тип. Например, для int
существует пара в виде Integer
. Последний представлен классом и называется классом-оберткой.
// Примитивный тип
// Можно так
var value = 42; // int
// Или так
int value = 42; // int
// Ссылочный тип
// Можно так
Integer value = 42; // Integer
Integer value = new Integer(42); // Integer
var value = new Integer(42); // Integer
// Так написать нельзя,
// потому что невозможно вывести тип value
// null может быть присвоено любому ссылочному типу
// var value = null;
То же самое и для всех остальных примитивных типов:
Примитивный тип | Класс-обертка |
---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
Классы-обертки нужны для нескольких целей, которых по разным причинам невозможно решить с помощью примитивных типов.
Совместимость и единообразие
Многие возможности Java завязаны на то, что типы представлены классами, только в этом случае они смогут быть использованы как параметры методов или их возвращаемое значение. К ним, например, относятся обобщенные типы и как их следствие коллекции. Все это мы рассмотрим в следующих курсах.
// Так написать нельзя
// var items = new ArrayList<int>;
var items = new ArrayList<Integer>;
null
Примитивные типы всегда содержат какое-то осмысленное значение. На практике же, значение может быть не определено. Особенно часто такое происходит, когда данные поступают из внешних источников. Для представления таких данных нужно специальное обозначение и возможность использовать это значение. В Java, как и в большинстве других языков, таким значением является null
. Его можно использовать только с классами-обертками.
// Ошибка!
int value = null;
// Работает
Integer value = null;
По этой причине, множество методов ожидает на вход классы-обертки, а не примитивные типы.
Утилиты и значения
Классы-обертки содержат в себе полезные значения и методы, для своих типов. Например, в Integer
есть данные о максимальном и минимальном значениях для типа, там же можно найти методы, которые преобразуют другие типы в числа.
var max = Integer.MAX_VALUE;
var min = Integer.MIN_VALUE;
// Преобразование в число
// Возвращает Integer
var value = Integer.valueOf("42"); // 42
// Возвращает int
var value = Integer.parseInt("42"); // 42
Почему так устроено?
Зачем тогда нужны примитивные типы если есть классы-обертки? Ответ кроется в производительности. Работа с примитивными типами как объектами значительно ухудшает производительность программы. Поэтому по умолчанию создаются объекты именно примитивных типов.
// Тип: boolean
var hasErrors = true;
Боксинг и анбоксинг (Boxing and Unboxing)
По логике, такая система должна приводить к постоянному конвертированию типов в коде, так как где-то создаются примитивные типы, где-то нужны классы-обертки и наоборот. К счастью, этого почти никогда не происходит благодаря механизму автобоксинга (Autoboxing). Тип преобразуется автоматически в тот момент, когда это нужно.
int value = 42;
// int -> Integer
Integer wrappedInt = value; // Autoboxing
// Integer ->
int unboxedInt = wrappedInt; // Auto-unboxing
По этой схеме работает и передача аргументов в методы и возврат из них.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.