Что такое боксинг и анбоксинг java

Autoboxing and Unboxing

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.

Here is the simplest example of autoboxing:

The rest of the examples in this section use generics. If you are not yet familiar with the syntax of generics, see the Generics (Updated) lesson.

Consider the following code:

Although you add the int values as primitive types, rather than Integer objects, to li, the code compiles. Because li is a list of Integer objects, not a list of int values, you may wonder why the Java compiler does not issue a compile-time error. The compiler does not generate an error because it creates an Integer object from i and adds the object to li. Thus, the compiler converts the previous code to the following at runtime:

Converting a primitive value (an int, for example) into an object of the corresponding wrapper class (Integer) is called autoboxing. The Java compiler applies autoboxing when a primitive value is:

Consider the following method:

Because the remainder (%) and unary plus (+=) operators do not apply to Integer objects, you may wonder why the Java compiler compiles the method without issuing any errors. The compiler does not generate an error because it invokes the intValue method to convert an Integer to an int at runtime:

Converting an object of a wrapper type (Integer) to its corresponding primitive (int) value is called unboxing. The Java compiler applies unboxing when an object of a wrapper class is:

The program prints the following:

Autoboxing and unboxing lets developers write cleaner code, making it easier to read. The following table lists the primitive types and their corresponding wrapper classes, which are used by the Java compiler for autoboxing and unboxing:

Источник

Что такое упаковка и распаковка(boxing/unboxing)?

Что это вообще такое упаковка и распаковка (boxing/unboxing) и зачем она нужна?

Был бы рад примерам.

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

3 ответа 3

их нельзя помещать в коллекции и прочее.

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

В тех случаях, когда по контексту требуются объекты (присваивание, вызов метода с передачей параметров), а мы используем значения примитивных типов (переменные или выражения типа 2 * 3), всегда происходит автоупаковка.

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

В версиях ниже JDK 1.5 было не легко преобразовывать примитивные типы данных, такие как int, char, float, double в их классы оболочки Integer, Character, Float, Double. Начиная с версии JDK 5 эта функция, преобразования примитивных типов в эквивалентные объекты, реализована автоматически. Это свойство известно как Автоупаковка(Autoboxing). Обратный процесс соответственно – Распаковка(Unboxing) т.е. процесс преобразования объектов в соответствующие им примитивные типы.

Пример кода для автоупаковки и распаковки представлен ниже:

Когда используется автоупаковка и распаковка?

Автоупаковка применяется компилятором Java в следующих условиях:

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

Всё ещё ищете ответ? Посмотрите другие вопросы с метками java java-faq или задайте свой вопрос.

Связанные

Похожие

Подписаться на ленту

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2021 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2021.12.9.40958

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Источник

Анбоксинг в современной Java

Вспомним старый добрый цикл for:

У такого синтаксиса уйма недостатков. Во-первых, переменная цикла упоминается три раза. Очень легко перепутать и упомянуть не ту переменную в одном или двух местах. Во-вторых, такая переменная не является effectively final. Её не передашь в явном виде в лямбды или анонимные классы. Но ещё важнее: нельзя застраховаться от случайного изменения переменной внутри цикла. Читать код тоже трудно. Если тело цикла большое, не так-то легко сказать, изменяется ли она ещё и внутри цикла, а значит непонятно, просто мы обходим числа по порядку или делаем что-то более сложное. Есть ещё потенциальные ошибки, если необходимо сменить направление цикла или включить границу. Да и выглядит это старомодно.

Во многих языках уже отошли от тяжёлого наследия Си и предлагают более современный синтаксис, когда вы просто указываете диапазон чисел. Например, возьмём Котлин:

Тут всё в шоколаде: переменная упоминается один раз, она неизменяемая внутри тела цикла, есть варианты для включения или исключения верхней границы, а также для задания шага. Красиво.

Можно ли приблизиться к этому варианту в Java? Да, с помощью цикла for-each, который появился в Java 5. Достаточно написать такой библиотечный метод в утилитном классе:

Никакого rocket science, исключительно тривиальный код, даже комментировать нечего. После этого вы легко можете писать красивые циклы и в Java:

Красиво. Можно явно объявить переменную final, чтобы запретить случайные изменения. Несложно сделать такие же методы с шагом или с включённой верхней границей и пользоваться ими. Почему же никто так до сих пор не делает? Потому что в данном случае из-за боксинга фатально страдает производительность. Давайте для примера посчитаем сумму кубов чисел в простеньком JMH-бенчмарке:

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

Понятно, что такие накладные расходы на обычный цикл for часто неприемлемы, поэтому программировать в таком стиле на Java никто всерьёз рекомендовать не будет. Однако давайте попробуем более новые версии Java:

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

Вот тут нас ждёт приятный сюрприз: начиная с Java 14 производительность варианта с range сравнялась с простой версией! JIT-компилятор стал достаточно умным, чтобы сгенерировать настолько же хороший ассемблер, как и в простой версии.

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

В Java 8-11 мы имели производительность на уровне 0,9 мкс, в 12 стало в районе 0,8, а начиная с 13 сравнялось с обычным циклом. И вот к Java 14 эта оптимизация стала достаточно стабильной, чтобы её включить по умолчанию. Вы можете пытаться сделать это и в более ранних версиях, но я бы не рекомендовал этого на серьёзном продакшне. Смотрите, например, какие страшные баги приходилось исправлять в связи с этой опцией.

Как видно, этот метод берёт значения в диапазоне от IntegerCache.low до IntegerCache.high из кэша, который заполняется на ранней стадии инициализации виртуальной машины. Поэтому, если у нас происходит боксинг с последующим анбоксингом, нельзя просто положиться на механизм скаляризации: иногда мы должны возвращать закэшированные объекты. В режиме AggressiveUnboxing JIT-компилятор принудительно начинает игнорировать этот кэш, если может доказать, что ссылка на объект никуда не уплывает. В этом можно убедиться, написав какой-нибудь такой код:

Мы грязным рефлекшном подменяем одно из чисел в кэше на другое, а затем в цикле сравниваем результат с тем, который должен получиться в результате подмены. В честной Java if не должен выполняться. Но с опцией AggressiveUnboxing мы получаем результат в духе

oops! 392146832; i = 333

То есть когда JIT-компилятор C2 добирается до метода rangeFor, он выкидывает обращение к испорченному кэшу, и начинает выдавать правильный ответ, который должен получаться, если бы мы не залезли в кэш грязными руками.

Источник

Автобокс и распаковка в Java

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг 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, вы можете проверить еще несколько ограничений вместе с этим.

Рекомендуемые статьи

Источник

Что такое boxing unboxing в java. Внутренний кэш классов оберток

Что такое боксинг и анбоксинг java. Смотреть фото Что такое боксинг и анбоксинг java. Смотреть картинку Что такое боксинг и анбоксинг java. Картинка про Что такое боксинг и анбоксинг java. Фото Что такое боксинг и анбоксинг java

Boxing и unboxing появились в java 1.5 для автоматической конвертации примитивных типов в Wrapper class, autoboxing позволяет использовать примитивы и Wrapper объекты взаимозаменяемыми в присвоении, вызовах методов и т.д. До версии java 1.5 при использовании коллекций Hashmap или ArrayList мы не могли добавить в коллекцию приметив, вместо этого необходимо сначала конвертировать их в Object и только потом можно добавить в коллекцию. С появление autoboxing и unboxing преобразование примитивов в объекты происходит автоматически на этапе компиляции.

Что такое boxing/unboxing в Java?

Когда Java автоматически преобразует примитивный тип напр. int в соответствующий класс Integer тогда это преобразование называется autoboxing, потому что примитив оборачивается в класс обертку, противоположное преобразование называется unboxing, когда Integer object преобразуется в примитивный тип int.

Все примитивные типы byte, short, char, int, long, float, double и boolean имеют соответствующие классы обертки. т.к. весь процесс преобразования происходит автоматически без единой строчки кода – этот процесс называется autoboxing/autounboxing.

Когда происходит autoboxing и unboxing

Autoboxing и unboxing выполняется все время когда ожидается объект, а передается примитив например в вызове метода в сигнатуре ожидается Объект, а передается примитивный тип, java автоматически конвертирует примитив в соответствующий объект. Классика использования autoboxing – добавление примитивов в коллекции такие как ArrayList, HashSet …

Autoboxing при присвоении

Autoboxing при вызове метода

Вызываем метод show(Integer) который принимает Integer в сигнатуре, при вызове метода с примитивом, int сначала конвертится в Integer далее вызывается метод. На втором вызове метода происходит unboxing т.к. show() метод возвращает Integer, а присваивается результат в int.

Скрытое создание объекта обертки в Java

При autoboxing нужно следить за непреднамеренным созданием объектов в цикле.

Код выше sum+=i представляется каа sum = sum + i и так как оператор + на применяется к объектам Integer, сначала выполняется unboxing sum далее autoboxing результата, который будет сохранен в переменной sum как Integer.

Так как sum это Integer object это создаст 4000 бесполезных объектов. Если это произойдет в большом масштабе это потенциально уменьшит производительность частыми вызовами GC. Для арифметических операций предпочитайте примитивы и следите за неявными преобразованием в Object (Boxed primitive)

Что нужно помнить при autoboxing в Java

Сравнение объектов оператором равенства (==)

Когда сравниваем два объекта используя “==” оператор сравнивает ссылки объектов, а не значения и autoboxing не происходит.

Выведет сообщение “Both ones are not equal” потому что не произошло автораспаковки. Ставится все более запутанным когда сравнение “==” применяется вместе с логическими операторами >

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *