Что такое autoboxing unboxing и когда они происходят автоматически
Автоупаковка и автораспаковка
Изучение новых функциональных возможностей, включенных в последнюю версию Java 2 5.0, начнем с так долго ожидаемых всеми программистами на языке Java автоупаковки (autoboxing) и автораспаковки (auto-unboxing). Выбор этот сделан по трем причинам. Во-первых, автоупаковка/автораспаковка сильно упрощает и рационализирует исходный код, в котором требуется объектное представление базовых типов языка Java, таких как int или char. Поскольку такие ситуации часто встречаются в текстах программ на Java, выигрыш от применения средств автоупаковки/распаковки получат практически все, программирующие на этом языке. Во-вторых, автоупаковка/автораспаковка во многом способствует простоте и удобству применения другого нового средства — настройки типов (generics). Следовательно, понимание автоупаковки и автораспаковки понадобится для последующего изучения этого механизма. В-третьих, автоупаковка/распаковка плавно изменяет наши представления о взаимосвязи объектов и данных базовых типов. Эти изменения гораздо глубже, чем может показаться на первый взгляд из-за концептуальной простоты двух описываемых здесь новых функциональных возможностей. Их влияние ощущается во всем языке Java.
Автоупаковка и автораспаковка напрямую связаны с оболочками типов (type wrapper) языка Java и со способом вставки значений в экземпляры таких оболочек и извлечения значений из них. По этой причине мы начнем с краткого обзора оболочек типов и процесса упаковки и распаковки значений для них.
Обзор оболочек типов и упаковки значений
Как вам известно, в языке Java используются базовые типы (также называемые простыми), такие как int или double, для хранения элементарных данных типов, поддерживаемых языком. Для хранения таких данных из-за более высокой производительности применяются базовые типы, а не объекты. В этом случае использование объектов добавляет неприемлемые издержки даже к простейшей вычислительной операции. Таким образом, базовые типы не являются частью иерархии объектов и не наследуют класс Object.
Несмотря на выигрыш в производительности, предлагаемый базовыми типами, возникают ситуации, требующие обязательного объектного представления. Например, Вы не можете передать в метод переменную базового типа как параметр по ссылке. Кроме того, много стандартных cтруктур данных, реализованных в языке Java, оперирует объектами, и, следовательно, Вы не можете использовать эти структуры для хранения данных базовых типов. Для подобных (и других) случаев Java предоставляет оболочки типов, представляющие собой классы, которые инкапсулируют данные простого типа в объект. Далее перечислены классы оболочки типов.
Значение базового типа инкапсулируется в оболочку в момент конструирования объекта. Упакованное таким образом значение можно получить обратно с помощью вызова одного из методов, определенных в оболочке. Например, все оболочки числовых типов предлагают следующие методы:
Каждый метод возвращает значение заданного базового типа. Например, объект типа Long может вернуть значение одного из встроенных числовых типов, включая short, double или long.
Процесс инкапсуляции значения в объект называется упаковкой (boxing). До появления Java 2 версии 5.0 вся упаковка выполнялась программистом вручную, с помощью создания экземпляра оболочки с нужным значением. В приведенной далее строке кода значение 100 упаковывается вручную в объект типа Integer:
В приведенном примере новый объект типа Integer со значением 100 создается явно и ссылка на него присваивается переменной iOb.
Процесс извлечения значения из оболочки типа называется распаковкой (unboxing). И снова, до появления Java 2 версии 5.0 вся распаковка выполнялась вручную с помощью вызова метода оболочки для получения значения из объекта.
В следующей строке кода значение из объекта iOb вручную распаковывается в переменную типа int:
В данном случае метод intValue() возвращает значение типа int из объекта iOb. Как объяснялось ранее, есть и другие методы, позволяющие извлечь из объекта значение другого числового типа, такого как byte, short, long, double или float. Например, для получения значения типа long из объекта iOb Вам следует вызвать метод iOb.longValue(). Таким образом, можно распаковать значение в переменную простого типа, отличающегося от типа оболочки.
Начиная с первоначальной версии языка Java, для упаковки и распаковки вручную выполнялась одна и та же базовая процедура, приведенная в предыдущих примерах. Хотя такой способ упаковки и распаковки работает, он утомителен и подвержен ошибкам, так как требует от программиста вручную создавать подходящий объект для упаковки значения и при необходимости его распаковки явно задавать переменную соответствующего базового типа. К счастью Java 2, v5.0 коренным образом модернизирует эти важнейшие процедуры, вводя средства автоупаковки/распаковки.
Основы автоупаковки/распаковки
Автоупаковка (autoboxing) — это процесс автоматической инкапсуляции данных простого типа, такого как int или double, в эквивалентную ему оболочку типа, как только понадобится объект этого типа. При этом нет необходимости в явном создании объекта нужного типа. Автораспаковка (auto-unboxing) — это процесс автоматического извлечения из упакованного объекта значения, когда оно потребуется. Вызовы методов, таких как intValue() и doubleValue(), становятся ненужными.
Добавление средств автоупаковки/автораспаковки значительно упрощает кодирование ряда алгоритмов, исключая утомительные упаковку и распаковку, выполняемые вручную. Кроме того, эти новые средства программирования позволяют избежать ошибок за счет устранения возможности распаковки вручную неверного типа из оболочки. Автоупаковка также облегчает использование настраиваемых типов (generics) и запоминание данных базовых типов в коллекциях.
Благодаря автоупаковке исчезает необходимость в создании вручную объекта для инкапсуляции значения простого типа. Вам нужно только присвоить это значение указателю на объект типа-оболочки. Язык Java автоматически создаст для вас этот объект. В следующей строке приведен пример современного способа конструирования объекта типа Integer, хранящего значение 100:
Обратите внимание на то, что никакого объекта не создается явно, с помощью операции new. Язык Java выполнит это автоматически.
Для автораспаковки объекта просто присвойте ссылку на него переменной соответствующего базового типа. Например, для распаковки объекта iOb можно использовать следующую строку кода:
Все детали выполнит для вас язык Java.
В листинге 2.1 приведена короткая программа, вобравшая в себя все приведенные ранее фрагменты и демонстрирующая основы механизма автоупаковки/распаковки,
Листинг 2.1. Демонстрация применения автоупаковки/распаковки
Обратите внимание еще раз на то, что не нужно явно создавать объект типа Integer для упаковки значения 100 и нет необходимости вызывать метод intValue() для распаковки этого значения.
Автоупаковка и методы
Помимо простых случаев присваивания, автоупаковка выполняется автоматически каждый раз, когда данные базового типа должны быть преобразованы в объект, а автораспаковка — при необходимости преобразования объекта в значение базового типа. Следовательно, автоупаковка/распаковка может происходить, когда аргумент передается в метод или когда значение возвращается методом. Рассмотрим пример, приведенный в листинге 2.2.
Листинг 2.2. Автоупаковка/распаковка параметров метода и возвращаемых им значений
Программа листинга 2.2 отображает следующий ожидаемый результат:
В приведенной программе метод задает параметр типа Integer и возвращает результат типа int. В теле main() методу m() передается значение 100. Поскольку ожидает объект типа Integer, передаваемое значение автоматически упаковывается. Далее метод то возвращает эквивалент своего аргумента, но простого типа int. Это приводит к автоматической распаковке в переменную v. Далее в методе main() объекту iOb присваивается это значение типа int, что вызывает его автоупаковку. Главное преимущество заключается в том, что все преобразования выполняются автоматически.
Автоупаковка/распаковка в выражениях
Вообще, автоупаковка/распаковка происходит всегда, когда требуется преобразование в объект или из объекта. Это применимо и к выражениям. В них числовой объект автоматически распаковывается. Результат выражения повторно упаковывается, если это необходимо. Рассмотрим программу, приведенную в листинге 2.3.
Листинг 2.3. Автоупаковка/распаковка внутри выражений
Далее приведен вывод программы, отображающий результаты ее работы.
Обратите особое внимание на следующую строку программы из листинга 2.3:
Она вызывает увеличение на единицу значения, упакованного в объекте iOb. Это действие выполняется следующим образом: объект iOb распаковывается, значение увеличивается, и результат повторно упаковывается.
Автораспаковка позволяет смешивать в выражении числовые объекты разных типов. После того как значения распакованы, к ним применимы стандартные преобразования типов и переходы от одного к другому. Например, приведенная в листинге 2.4 программа вполне корректна.
Листинг 2.4. Обработка числовых объектов разных типов в одном выражении
Далее приведен результат работы программы из листинга 2.4.
Как видите, и объект dOb типа Double, и объект iOb типа Integer участвовали в сложении, а результат был повторно упакован и сохранен в объекте dOb.
Благодаря автораспаковке Вы можете использовать целочисленный объект для управления оператором switch. Рассмотрим следующий фрагмент программы:
Когда вычисляется выражение в операторе switch, распаковывается объект iOb и извлекается значение типа int.
Приведенные примеры программ показывают, что наличие автоупаковки/распаковки делает использование числовых объектов в выражении легким и интуитивно понятным. В прошлом в этот код пришлось бы вставлять вызовы методов, подобных intValue().
Автоупаковка/распаковка логических и символьных значений
Кроме оболочек для числовых типов язык Java также предоставляет оболочки для данных типов boolean и char. Они называются Boolean и Character соответственно. К ним также применимы автоупаковка/распаковка. Рассмотрим программу, приведенную в листинге 2.5.
Листинг 2.5. Автоупаковка/распаковка типов Boolean и Character
Далее приведен вывод программы из листинга 2.5, отображающий результаты ее работы:
Наиболее важной в программе из листинга 2.5 является автораспаковка объекта b внутри условного выражения в операторе if. Как вы должны помнить, условное выражение, управляющее выполнением оператора if, следует вычислять как значение типа boolean. Благодаря наличию автораспаковки логическое значение, содержащееся в объекте b, автоматически распаковывается при вычислении условного выражения. Таким образом, с появлением Java 2 v5.0 стало возможным использование объекта типа Boolean для управления оператором if.
Более того, теперь объект типа Boolean можно применять для управления любыми операторами цикла языка Java. Когда объект типа Boolean используется как условное выражение в циклах while, for, do/while, он автоматически распаковывается в эквивалент простого типа boolean. Например, приведенный далее фрагмент теперь абсолютно корректен.
Помощь автоупаковки/распаковки в предупреждении ошибок
Кроме удобства, которое предоставляет механизм автоупаковки/распаковки, он может помочь в предупреждении ошибок. Рассмотрим программу, приведенную в листинге 2.6.
Листинг 2.6. Ошибка, возникшая при распаковке вручную
Вообще говоря, поскольку автоупаковка всегда создает правильный объект, а автораспаковка всегда извлекает надлежащее значение, не возникает ситуаций для формирования неверного типа объекта или значения. В редких случаях, когда Вам нужен тип, отличающийся от созданного автоматическим процессом, Вы и сейчас можете упаковывать и распаковывать значения вручную так, как делали это раньше. Конечно, при этом теряются преимущества автоупаковки/распаковки. Как правило, во вновь разрабатываемом коде должны применяться эти механизмы, так как они соответствуют современному стилю программирования на языке Java.
Предостережения
Теперь, когда в язык Java включены средства автоупаковки/распаковки, может появиться желание использовать только числовые объекты типа Integer или Double, полностью отказавшись от данных простых типов. Например, благодаря наличию автоупаковки/распаковки теперь можно написать код, подобный приведенному далее.
Пример плохого использования автоупаковки/распаковки Double a,b,c;
В приведенном примере объекты типа Double содержат значения, которые используются для вычисления гипотенузы прямоугольного треугольника. Хотя этот код технически корректен и будет выполняться правильно, он служит образцом очень плохого применения автоупаковки/распаковки. Гораздо эффективнее использовать данные простого типа double для подобных вычислений, т. к. каждая автоупаковка и автораспаковка вносят дополнительные затраты, которых лишены вычисления с применением базовых типов данных.
Вообще говоря, следует ограничить использование оболочек типов только теми случаями, для которых требуется объектное представление данных простых типов. Автоупаковка/автораспаковка включены в язык таким образом, чтобы не ограничивать применение простых типов данных.
Автобокс и распаковка в Java
Введение в Autoboxing и Unboxing в Java
import java.util.ArrayList;
public class MyClass (
public static void main(String args()) (
ArrayList intlist = new ArrayList();
//wrapper Integer objects being added here
intlist.add(1);
interest.add(2);
//auto-unboxing is happening here
int x = intlist.get(0);
System.out.println(x);
)
)
public class MyClass (
public static void main(String args()) (
Integer sum =0;
for(int i=0;i
Рассмотрите фрагмент, размещенный ниже, как вы думаете, что будет результатом этого?
public class Main
(
public static void main(String() args) (
Integer m = 34123;
Integer x = 34123;
System.out.println(x==m);
)
)
public class Main
(
public static void main(String() args) (
Integer m = 100;
Integer x = 100;
System.out.println(x==m);
)
)
Это приведет к «истинному» значению, так как 100 присутствует в буквальном пуле.
Автобокс и распаковка в Java с перегрузкой метода
public class Main
(
public static void main(String() args) (
Overload obj = new Overload();
int i =5;
obj.printval(5);
Integer m = i;
obj.printval(m);
)
)
class Overload
(
public void printval(int i)
(
System.out.println(«printing the unboxed value «+ i);
)
public void printval(Integer i)
(
System.out.println(«printing the autoboxed value «+ i);
)
)
печать распакованного значения 5
печать автобоксов 5
Примечание. Вы можете запустить вышеуказанную программу в любой из IDE, чтобы получить вывод выше.
Преимущества Autoboxing и Unboxing в Java-
Вывод
Мы увидели сценарий использования автобоксирования и распаковки, насколько неявна эта концепция и где она может создавать плюсы и минусы. Он должен использоваться с осторожностью при кодировании, иначе он может добавить ненужные накладные расходы на вычислительное преобразование, поэтому преобразования должны выполняться в примитивах, чтобы избежать чрезмерных затрат на сборку мусора и чрезмерного создания временных объектов. Мы также видели случай использования автоматической коробки с концепцией перегрузки Java, вы можете проверить еще несколько ограничений вместе с этим.
Рекомендуемые статьи
Русские Блоги
Глубокое понимание механизма автоматической упаковки и распаковки Java (Autoboxing и unboxing)
1. Определение автоматического бокса и распаковки
Простой тип | Двоичные цифры | Класс-оболочка |
---|---|---|
int | 32 | Integer |
byte | 8 | Byte |
long | 64 | Long |
float | 32 | float |
double | 64 | Double |
char | 16 | Character |
boolean | 1 | Boolean |
Автоматический бокс
Сначала посмотрите на следующий код:
Автоматическая распаковка
Сначала посмотрите на следующий код:
похожие темы
Автоматическая упаковка и распаковка решены, посмотрите, что выводит следующий код:
Три приведенных выше фрагмента кода: Результат кода 1 верен, что легче понять: как показано ниже:
Но почему результат кода 2 верен? Знайте из вышеупомянутого автоматического бокса
Разве он не сгенерировал также два объекта c и d? Почему выходной результат верен. На самом деле это связано с автоматическим боксом. Давайте посмотрим на исходный код автоматического бокса:
В приведенном выше коде: IntegerCache.cache [i + 127]; Что это такое? Вот упрощенный исходный код:
подводить итоги
Выше было объяснено автоматическое упаковывание и распаковка базового типа int, на самом деле int byte short long float double char boolean Эти основные типы процессов автоматической упаковки и распаковки аналогичны.
Класс обертки На Java | Примеры Автоматической Упаковки И Распаковки
В этой статье рассматривается класс-оболочка в java с эквивалентными объектами класса-оболочки примитивных типов данных с примерами автоматической упаковки и распаковки.
Автор оригинала: Waseem.
Язык программирования Java является одним из самых популярных языков программирования в настоящее время. С такими понятиями, как переменные, типы данных, классы и объекты, возникает еще одна важная концепция класса-оболочки в java, которая необходима для синхронизации в многопоточности, структуре сбора и т.д. В этой статье мы обсудим необходимость класса-оболочки в java на различных примерах. Ниже приведены концепции, обсуждаемые в этом блоге:
Что Такое Класс Java – Оболочки?
Класс-оболочка предоставляет механизм преобразования примитивных типов данных в объекты класса-оболочки. Ниже приведены эквивалентные объекты класса-оболочки примитивных типов данных.
Ниже приведен пример, показывающий, как можно создать объект класса java-оболочки.
В приведенной выше программе мы использовали класс-оболочку вместо примитивных типов данных.
Ниже приведены методы получения соответствующего значения из объектов-оболочек.
Ниже приведен пример использования этих методов в программе:
Аналогичным образом вы можете использовать другие методы, такие как double Value (), shortValue (), longValue (), byte Value (), чтобы получить соответствующие значения объектов класса-оболочки.
Потребность В Классе Java-Оболочки
Автобокс
Автобокс-это автоматическое преобразование примитивных типов данных в объекты соответствующего класса-оболочки.
Распаковка
Это обратная сторона автобокса, когда объект класса-оболочки преобразуется в соответствующий примитивный тип данных.
В этой статье мы обсудили класс-оболочку в java, который помогает преобразовывать примитивные типы данных в соответствующие им объекты. Это помогает в синхронизации во время многопоточности, а также в различных других приложениях. Java – универсальный язык с множеством эффективных и революционных концепций.
У вас есть к нам вопрос? Пожалуйста, упомяните об этом в разделе комментариев статьи “Класс-оболочка в Java”, и мы свяжемся с вами как можно скорее.
Почему мы используем autoboxing и unboxing в Java?
Итак, зачем нам это нужно и почему мы используем autoboxing и unboxing в Java?
ОТВЕТЫ
Ответ 1
Некоторый контекст необходим, чтобы полностью понять основную причину этого.
Примитивы против классов
Примитивные переменные в Java содержат значения (целое число, двоичное число с плавающей запятой двойной точности и т.д.). Поскольку эти значения могут иметь разную длину, переменные, содержащие их, также могут иметь разную длину (рассмотрите float по сравнению с double ).
Это свойство переменных класса делает ссылки на них взаимозаменяемыми (в некоторой степени). Это позволяет нам делать то, что мы называем заменой: в широком смысле использовать экземпляр определенного типа в качестве экземпляра другого связанного типа (например, используйте String как Object ).
Дженерики и стирание типов
Поместите два вместе
Ответ 2
требуется, потому что программисты могут легко писать код, а JVM позаботится о боксе и распаковке.
Auto Boxing также пригодится, когда мы работаем с типами java.util.Collection. Когда мы хотим создать коллекцию примитивных типов, мы не можем напрямую создавать коллекцию примитивного типа, мы можем создавать только коллекцию объектов. Например:
Классы Wrapper
Использование Классы Wrapper
Существует множество полезных функций, которые предоставляют классы Wrapper. Ознакомьтесь с java docs здесь
Unboxing противоположно Auto Boxing, где мы конвертируем объект класса-оболочки обратно в его примитивный тип. Это делается автоматически с помощью JVM, поэтому мы можем использовать классы-оболочки для определенной операции, а затем преобразовывать их обратно в примитивные типы, поскольку примитивы приводят к более быстрой обработке. Например:
В случае Коллекций, которые работают с объектами, используется только автоматическое разблокирование. Вот как:
Ответ 3
У примитивных (не объектов) типов есть обоснование эффективности.
Примитивные типы int, boolean, double являются непосредственными данными, тогда как Object являются ссылками. Следовательно, поля (или переменные)
нужна локальная память 4 + 8 + 8? где для объекта сохраняется только ссылочный (адрес) в память.
Используя обертки объектов Integer, Double и другие, можно ввести косвенную ссылку на некоторый экземпляр Integer/Double в памяти кучи.
Почему нужен бокс?
Ответ:. Теперь ArrayList работает только для Object, резервируя место для ссылки на объект и также управляя сборкой мусора. Следовательно, общие типы являются объектными детьми. Поэтому, если вам нужен ArrayList значений с плавающей запятой, необходимо обернуть двойной объект Double.
Таким образом, без бокса для Object один нужно будет скомпилировать классы для каждого вхождения типа параметра. В concreto: каждому классу коллекции или контейнера понадобится версия для Object, int, double, boolean. Версия для Object будет обрабатывать все дочерние классы.
Фактически, потребность в такой диверсификации уже существовала в Java SE для IntBuffer, CharBuffer, DoubleBuffer. которые работают с int, char, double. Это было разрешено хакерским путем, генерируя эти источники из общего.
Ответ 4
Добавление автобоксинга и автоматической распаковки значительно упрощает алгоритмы записи, устраняя приманку вручную бокс и распаковку значений. Также полезно избежать ошибок. Также очень важно для дженериков, которые работают только с объектами. Наконец, autoboxing облегчает работу с Коллекции Framework.
Ответ 5
почему у нас есть (un) бокс?
сделать код записи, где мы смешиваем примитивы и их объектно-ориентированные (OO) альтернативы более удобные/менее подробные.
почему у нас есть примитивы и их альтернативы OO?
примитивные типы не являются классами (в отличие от С#), поэтому они не являются подклассами Object и не могут быть переопределены.
Преимущества OO наиболее легко видны с помощью Generics ( List ), но не ограничиваются этим, например:
Ответ 6
Потому что они разные, и в качестве удобства. Вероятно, производительность является причиной наличия примитивных типов.
Ответ 7
Некоторые структуры данных могут принимать только объекты, примитивные типы.
Пример: ключ в HashMap.
Подробнее см. этот вопрос: HashMap и int как ключ
Есть и другие веские причины, такие как поле «int» в базе данных, которое также может быть NULL. Int в Java не может быть null; может использоваться целая ссылка. Автобоксинг и распаковка предоставляют возможность избежать постороннего кода в преобразованиях назад и вперед.
Ответ 8
Когда требуется?
Когда метод ожидает объект класса-оболочки, но значение, которое передается как параметр, является примитивным типом. Когда примитивное значение присваивается переменной класса оболочки или наоборот.
Не нужно явно создавать объект и обертывать значение примитивного типа.
Неудобство
«Автобоксинг» слишком неожиданен в своем поведении и может легко привести к затруднению распознавания ошибок.
Производительность
Autoboxing создает объекты, которые явно не видны в коде. Поэтому, когда аутобоксинг происходит, производительность страдает.
Ответ 9
ArrayList не поддерживает примитивные типы, только поддерживает класс. но нам нужно использовать примитивные типы, например, int, double и т.д.
Класс Integer оборачивает значение примитивного типа int в object.so, нижеприведенный код принят.
мы можем добавить значение с помощью метода add (value). Чтобы добавить строковое значение, скажите «Hello» в коде strArrayList просто
и добавить значение INT скажем, 54 мы можем написать
но когда мы пишем intArrayList.add(54); компилятор преобразовать в следующую строку
Поскольку intArrayList.add(54) является простым и более приемлемым для пользовательской стороны, компилятор выполняет тяжелую работу, которая представляет собой intArrayList.add(Integer.valueOf(54)); это автобокс.
Аналогично, чтобы получить значение, мы просто набираем intArrayList.get(0) и компилятор конвертируется в intArrayList.get(0).intValue(); который является autoUnboxing.
Ответ 10
Автобокс: преобразование примитивного значения в объект соответствующего класса-оболочки.
Распаковка: преобразование объекта типа оболочки в соответствующее примитивное значение