1. Обзор
Как следует из названия, классы-оболочки — это объекты, инкапсулирующие примитивные типы Java.
Каждый примитив Java имеет соответствующую оболочку:
логическое, байтовое, короткое, символьное, целое, длинное, плавающее, двойное
Логическое, байтовое, короткое, символьное, целое, длинное, с плавающей запятой,
двойное
Все они определены в пакете java.lang
, поэтому нам не нужно импортировать их вручную.
2. Классы-оболочки
«Какова цель класса-оболочки?». Это один из самых распространенных вопросов на собеседовании по Java .
По сути, универсальные классы работают только с объектами и не поддерживают примитивы . В результате, если мы хотим работать с ними, мы должны преобразовать примитивные значения в объекты-оболочки.
Например, Java Collection Framework работает исключительно с объектами. Давным-давно (до Java 5, почти 15 лет назад) не было автоупаковки, и мы, например, не могли просто вызвать add(5)
для набора целых чисел.
В то время эти примитивные
значения необходимо было вручную преобразовать в соответствующие
классы-оболочки и сохранить в коллекциях.
Сегодня, с автоупаковкой, мы можем легко сделать ArrayList.add(101)
, но внутренне Java преобразует примитивное значение в Integer
, прежде чем сохранить его в ArrayList
, используя метод valueOf ()
.
3. Преобразование примитивного класса в оболочку
Теперь большой вопрос: как нам преобразовать примитивное значение в соответствующий класс-оболочку, например, int
в Integer
или char
в Character?
Что ж, мы можем использовать либо конструктор, либо статические фабричные методы для преобразования примитивного значения в объект класса-оболочки.
Однако начиная с Java 9 конструкторы для многих упакованных примитивов, таких как Integer
или Long
, устарели.
Поэтому настоятельно рекомендуется использовать фабричные методы только для нового кода .
Давайте посмотрим на пример преобразования значения int
в объект Integer
в Java:
Integer object = new Integer(1);
Integer anotherObject = Integer.valueOf(1);
Метод valueOf()
возвращает экземпляр, представляющий указанное значение int
.
Он возвращает кэшированные значения, что делает его эффективным. Он всегда кэширует значения от -128 до 127, но также может кэшировать другие значения за пределами этого диапазона.
Точно так же мы можем преобразовать логическое значение
в логическое, байтовое
в байтовое , символьное
в символьное, длинное
в длинное, плавающее
в плавающее
и двойное
в двойное.
Хотя, если нам нужно преобразовать String в Integer , нам нужно использовать метод parseInt() , потому что
String
не является классом-оболочкой.
С другой стороны, чтобы преобразовать объект-оболочку в примитивное значение, мы можем использовать соответствующий метод, такой как intValue(), doubleValue() и
т. д .:
int val = object.intValue();
Подробную справку можно найти здесь .
4. Автоупаковка и распаковка
В предыдущем разделе мы показали, как вручную преобразовать примитивное значение в объект.
После Java 5 это преобразование может выполняться автоматически с помощью функций, называемых автоупаковкой и распаковкой.
«Бокс» относится к преобразованию примитивного значения в соответствующий объект-оболочку. Поскольку это может происходить автоматически, это называется автобоксингом.
Точно так же, когда объект-оболочка разворачивается в примитивное значение, это называется распаковкой.
На практике это означает, что мы можем передать примитивное значение методу, который ожидает объект-оболочку, `` или присвоить примитив переменной, которая ожидает объект:
List<Integer> list = new ArrayList<>();
list.add(1); // autoboxing
Integer val = 2; // autoboxing
В этом примере Java автоматически преобразует примитивное значение int
в оболочку.
Внутри он использует метод valueOf()
для облегчения преобразования. Например, следующие строки эквивалентны:
Integer value = 3;
Integer value = Integer.valueOf(3);
Хотя это упрощает преобразование и делает код более читаемым, в некоторых случаях мы не должны использовать автоупаковку, например, внутри цикла .
Подобно автоупаковке, распаковка выполняется автоматически при передаче объекта методу, который ожидает примитив, или при присвоении его примитивной переменной:
Integer object = new Integer(1);
int val1 = getSquareValue(object); //unboxing
int val2 = object; //unboxing
public static int getSquareValue(int i) {
return i*i;
}
По сути, если мы напишем метод, который принимает примитивное значение или объект-оболочку, мы все равно можем передать им оба значения. Java позаботится о передаче правильного типа, например, примитива или оболочки, в зависимости от контекста.
5. Вывод
В этом кратком руководстве мы рассказали о классах-оболочках в Java, а также о механизме автоупаковки и распаковки.