Почему мы используем autoboxing и unboxing в Java?
Autoboxing - это автоматическое преобразование, которое компилятор Java делает между примитивными типами и их соответствующей оберткой объекта классы. Например, преобразование int в Integer, двойное к Двойной и т.д. Если преобразование идет другим путем, это называется unboxing.
Итак, зачем нам это нужно и почему мы используем autoboxing и unboxing в Java?
Ответы
Ответ 1
Некоторый контекст необходим, чтобы полностью понять основную причину этого.
Примитивы против классов
Примитивные переменные в Java содержат значения (целое число, двоичное число с плавающей запятой двойной точности и т.д.). Поскольку эти значения могут иметь разную длину, переменные, содержащие их, также могут иметь разную длину (рассмотрите float
по сравнению с double
).
С другой стороны, переменные класса содержат ссылки для экземпляров. Ссылки обычно реализуются как указатели (или что-то очень похожее на указатели) на многих языках. Обычно эти вещи имеют одинаковый размер независимо от размеров экземпляров, на которые они ссылаются (Object
, String
, Integer
и т.д.).
Это свойство переменных класса делает ссылки на них взаимозаменяемыми (в некоторой степени). Это позволяет нам делать то, что мы называем заменой: в широком смысле использовать экземпляр определенного типа в качестве экземпляра другого связанного типа (например, используйте String
как Object
).
Примитивные переменные не являются взаимозаменяемыми одинаково, ни друг с другом, ни с Object
. Наиболее очевидной причиной этого (но не единственной причины) является их разность в размерах. Это делает примитивные типы неудобными в этом отношении, но мы все еще нуждаемся в них на языке (по причинам, которые в основном сводятся к производительности).
Дженерики и стирание типов
Общие типы - это типы с одним или несколькими параметрами типа (точное число называется общей арностью). Например, определение типового типа List<T>
имеет параметр типа T
, который может быть Object
(создающий конкретный тип List<Object>
), String
(List<String>
), Integer
(List<Integer>
) и т.д.
Общие типы намного сложнее, чем не общие. Когда они были введены в Java (после его первоначального выпуска), чтобы избежать радикальных изменений в JVM и, возможно, нарушить совместимость со старыми двоичными файлами, создатели Java решили внедрить родовые типы наименее инвазивным способом:/strong > все конкретные типы List<T>
на самом деле скомпилированы в (двоичный эквивалент) List<Object>
(для других типов граница может быть чем-то отличным от Object
, но вы получаете эту точку). Общая информация о параметрах arty и type теряется в этом процессе, поэтому мы называем это type erasure.
Поместите два вместе
Теперь проблема заключается в сочетании вышеуказанных реалий: если List<T>
становится List<Object>
во всех случаях, тогда T
всегда должен быть типом, который может быть непосредственно назначен Object
. Ничего другого нельзя разрешить. Поскольку, как мы уже говорили ранее, int
, float
и double
не взаимозаменяемы с Object
, не может быть List<int>
, List<float>
или List<double>
(если только значительно более сложный реализация дженериков существовала в JVM).
Но Java предлагает такие типы, как Integer
, float
и double
, которые переносят эти примитивы в экземпляры классов, делая их эффективно заменяемыми как Object
, таким образом позволяет родовые типы косвенно работать с примитивами (потому что вы можете иметь List<Integer>
, List<float>
, List<double>
и т.д.).
Процесс создания Integer
из int
, a float
из a float
и т.д. называется boxing. Реверс называется распаковкой. Поскольку наличие полевых примитивов каждый раз, когда вы хотите использовать их как Object
, неудобно, есть случаи, когда язык делает это автоматически - который называется autoboxing.
Ответ 2
Auto Boxing используется , чтобы преобразовать примитивные типы данных в их объекты класса-оболочки.
Класс Wrapper обеспечивает широкий диапазон функций, которые должны выполняться на примитивных типах. Наиболее распространенный пример:
int a = 56;
Integer i = a; // Auto Boxing
требуется, потому что программисты могут легко писать код, а JVM позаботится о боксе и распаковке.
Auto Boxing также пригодится, когда мы работаем с типами java.util.Collection. Когда мы хотим создать коллекцию примитивных типов, мы не можем напрямую создавать коллекцию примитивного типа, мы можем создавать только коллекцию объектов. Например:
ArrayList<int> al = new ArrayList<int>(); // not supported
ArrayList<Integer> al = new ArrayList<Integer>(); // supported
al.add(45); //auto Boxing
Классы Wrapper
Каждый из примитивных типов Java 8 (byte, short, int, float, char, double, boolean, long) hava - отдельный класс Wrapper, связанный с ними. Эти классы Wrapper имеют предопределенные методы предварительной обработки полезных операций с примитивными типами данных.
Использование Классы Wrapper
String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.
Существует множество полезных функций, которые предоставляют классы Wrapper. Ознакомьтесь с java docs здесь
Unboxing противоположно Auto Boxing, где мы конвертируем объект класса-оболочки обратно в его примитивный тип. Это делается автоматически с помощью JVM, поэтому мы можем использовать классы-оболочки для определенной операции, а затем преобразовывать их обратно в примитивные типы, поскольку примитивы приводят к более быстрой обработке. Например:
Integer s = 45;
int a = s; auto UnBoxing;
В случае Коллекций, которые работают с объектами, используется только автоматическое разблокирование. Вот как:
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);
int a = al.get(0); // returns the object of Integer . Automatically Unboxed .
Ответ 3
У примитивных (не объектов) типов есть обоснование эффективности.
Примитивные типы int, boolean, double
являются непосредственными данными, тогда как Object
являются ссылками. Следовательно, поля (или переменные)
int i;
double x;
Object s;
нужна локальная память 4 + 8 + 8? где для объекта сохраняется только ссылочный (адрес) в память.
Используя обертки объектов Integer, Double
и другие, можно ввести косвенную ссылку на некоторый экземпляр Integer/Double в памяти кучи.
Почему нужен бокс?
Это вопрос относительной сферы. В будущем java планируется иметь ArrayList<int>
, примитивные типы подъема.
Ответ:. Теперь ArrayList работает только для Object, резервируя место для ссылки на объект и также управляя сборкой мусора. Следовательно, общие типы являются объектными детьми.
Поэтому, если вам нужен ArrayList значений с плавающей запятой, необходимо обернуть двойной объект Double.
Здесь Java отличается от традиционного С++ своими шаблонами: классы С++ vector<string>, vector<int>
будут создавать два компиляционных продукта. В Java-дизайне появился один ArrayList.class, не требующий для каждого типа параметра нового скомпилированного продукта.
Таким образом, без бокса для Object один нужно будет скомпилировать классы для каждого вхождения типа параметра. В concreto: каждому классу коллекции или контейнера понадобится версия для Object, int, double, boolean. Версия для Object будет обрабатывать все дочерние классы.
Фактически, потребность в такой диверсификации уже существовала в Java SE для IntBuffer, CharBuffer, DoubleBuffer,... которые работают с int, char, double. Это было разрешено хакерским путем, генерируя эти источники из общего.
Ответ 4
Начиная с JDK 5, java добавила две важные функции: автобоксинг и аутоунбоксинг. AutoBoxing - это процесс, для которого примитивный тип автоматически инкапсулируется в эквивалентной оболочке всякий раз, когда нужен такой объект. Вам не нужно явно конструировать объект. Автоматическая распаковка - это процесс, при котором значение инкапсулированного объекта автоматически извлекается из обертки типа, когда требуется его значение. Вам не нужно вызывать метод, такой как intValue() или doubleValue().
Добавление автобоксинга и автоматической распаковки значительно упрощает алгоритмы записи, устраняя приманку вручную бокс и распаковку значений. Также полезно избежать ошибок. Также очень важно для дженериков, которые работают только с объектами. Наконец, autoboxing облегчает работу с Коллекции Framework.
Ответ 5
почему у нас есть (un) бокс?
сделать код записи, где мы смешиваем примитивы и их объектно-ориентированные (OO) альтернативы более удобные/менее подробные.
почему у нас есть примитивы и их альтернативы OO?
примитивные типы не являются классами (в отличие от С#), поэтому они не являются подклассами Object
и не могут быть переопределены.
у нас есть примитивы типа int
по соображениям производительности и альтернативы Object
, такие как Integer
для преимуществ программирования OO, а в качестве второстепенной точки - хорошее расположение для констант и методов полезности (Integer. MAX_VALUE и Integer.toString(int)
).
Преимущества OO наиболее легко видны с помощью Generics (List<Integer>
), но не ограничиваются этим, например:
Number getMeSome(boolean wantInt) {
if (wantInt) {
return Integer.MAX_VALUE;
} else {
return Long.MAX_VALUE;
}
}
Ответ 6
Потому что они разные, и в качестве удобства. Вероятно, производительность является причиной наличия примитивных типов.
Ответ 7
Некоторые структуры данных могут принимать только объекты, примитивные типы.
Пример: ключ в HashMap.
Подробнее см. этот вопрос: HashMap и int как ключ
Есть и другие веские причины, такие как поле "int" в базе данных, которое также может быть NULL.
Int в Java не может быть null; может использоваться целая ссылка. Автобоксинг и распаковка предоставляют возможность избежать постороннего кода в преобразованиях назад и вперед.
Ответ 8
Когда требуется?
Когда метод ожидает объект класса-оболочки, но значение, которое передается как параметр, является примитивным типом. Когда примитивное значение присваивается переменной класса оболочки или наоборот.
<сильные > Преимущества
Не нужно явно создавать объект и обертывать значение примитивного типа.
Неудобство
"Автобоксинг" слишком неожиданен в своем поведении и может легко привести к затруднению распознавания ошибок.
Производительность
Autoboxing создает объекты, которые явно не видны в коде. Поэтому, когда аутобоксинг происходит, производительность страдает.
Подробнее о.... Автобоксинг и распаковка
Rj
Ответ 9
ArrayList не поддерживает примитивные типы, только поддерживает класс. но нам нужно использовать примитивные типы, например, int, double и т.д.
ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted.
ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.
Класс Integer оборачивает значение примитивного типа int в object.so, нижеприведенный код принят.
ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.
мы можем добавить значение с помощью метода add (value). Чтобы добавить строковое значение, скажите "Hello" в коде strArrayList просто
strArrayList.add("Hello");
и добавить значение INT скажем, 54 мы можем написать
intArrayList.add(54);
но когда мы пишем intArrayList.add(54); компилятор преобразовать в следующую строку
intArrayList.add(Integer.valueOf(54));
Поскольку intArrayList.add(54) является простым и более приемлемым для пользовательской стороны, компилятор выполняет тяжелую работу, которая представляет собой intArrayList.add(Integer.valueOf(54));
это автобокс.
Аналогично, чтобы получить значение, мы просто набираем intArrayList.get(0) и компилятор конвертируется в <code>intArrayList.get(0).intValue();
который является autoUnboxing.
Ответ 10
Автобокс: преобразование примитивного значения в объект соответствующего класса-оболочки.
Распаковка: преобразование объекта типа оболочки в соответствующее примитивное значение
// Java program to illustrate the concept
// of Autoboxing and Unboxing
import java.io.*;
class GFG
{
public static void main (String[] args)
{
// creating an Integer Object
// with value 10.
Integer i = new Integer(10);
// unboxing the Object
int i1 = i;
System.out.println("Value of i: " + i);
System.out.println("Value of i1: " + i1);
//Autoboxing of char
Character gfg = 'a';
// Auto-unboxing of Character
char ch = gfg;
System.out.println("Value of ch: " + ch);
System.out.println("Value of gfg: " + gfg);
}
}