Почему мы используем автобоксинг и распаковку в Java?
Autoboxing-Это автоматическое преобразование, которое делает компилятор Java между примитивными типами и соответствующей им оболочкой объектов занятия. Например, преобразование int в целое число, double в a Двойной и так далее. Если преобразование идет в другую сторону, это называется распаковка.
Так зачем нам это нужно и почему мы используем автобоксинг и распаковку в Java?
7 ответов
требуется некоторый контекст, чтобы полностью понять основную причину этого.
примитивы против классов
примитивные переменные в Java содержат значения (целое число, двоичное число с плавающей запятой двойной точности и т. д.). Потому что эти значения могут иметь разную длину, переменные, содержащие их, также могут иметь различную длину (рассмотрим float
и double
).
С другой стороны, класс переменные содержат ссылки в случаях. Ссылки обычно реализуются как указатели (или что-то очень похожее на указатели) на многих языках. Эти вещи обычно имеют одинаковый размер, независимо от размеров экземпляров, на которые они ссылаются (Object
, String
, Integer
и т. д.).
это свойство переменных класса делает ссылки, которые они содержат заменимые (в определенной степени). Это позволяет нам делать то, что мы называем замена: в общем,использовать экземпляр определенного типа в качестве экземпляра другого связанного типа (использовать String
как Object
, например).
примитивные переменные не заменимый точно так же, ни друг с другом, ни с Object
. Наиболее очевидной причиной этого (но не единственной) является их разница в размерах. Это делает примитивные типы неудобными в этом отношении, но мы все еще нуждаемся в них в язык (по причинам, которые в основном сводятся к производительности).
дженерики и стирание типа
универсальные типы-это типы с одним или несколькими параметры типа (точное число называется общий arity). Например,определение универсального типа List<T>
имеет параметр типа T
, который может быть Object
(производства конкретного типа List<Object>
), String
(List<String>
), Integer
(List<Integer>
) и так на.
общие типы намного сложнее, чем неродовые. Когда они были введены в Java (после его первоначального выпуска), чтобы избежать внесения радикальных изменений в JVM и, возможно, нарушения совместимости со старыми двоичными файлами,создатели Java решили реализовать универсальные типы наименее инвазивным способом: все конкретные типы List<T>
фактически скомпилированы в (двоичный эквивалент)List<Object>
(для других типов, может быть что-то кроме Object
, но вы получите точку). Общие сведения arity и тип параметра теряются в этом процессе, вот почему мы называем это стирания типа.
поставить два вместе
теперь проблема заключается в сочетании вышеуказанных реальностей: если List<T>
становится List<Object>
во всех случаях, то T
всегда должен быть тип, который может быть непосредственно назначен Object
. Ничего не может быть допустимый. Поскольку, как мы уже говорили,int
, float
и double
не взаимозаменяемы с Object
не может быть List<int>
, List<float>
или List<double>
(если только в JVM не существовало значительно более сложной реализации дженериков).
но Java предлагает такие типы, как Integer
, Float
и Double
которые обертывают эти примитивы в экземплярах класса, делая их эффективно заменяемыми как Object
, таким образом разрешить общим типам косвенно работать с примитивы!--48--> также (потому что вы can есть List<Integer>
, List<Float>
, List<Double>
и так далее).
процесс создания Integer
С int
, a Float
С float
и так далее, называется бокс. Обратное называется анбоксинг. Потому что в коробке примитивы каждый раз, когда вы хотите использовать их как Object
неудобно, есть случаи, когда язык делает это автоматически - это называется автоупаковка.
Автомобильный Бокс is используется для преобразования примитивных типов данных в объекты класса-оболочки. Класс-оболочка предоставляет широкий диапазон функций для выполнения примитивных типов. Самый распространенный пример :
int a = 56;
Integer i = a; // Auto Boxing
Это нужны из-за программистов легко иметь возможность напрямую писать код, и JVM позаботится о боксе и распаковке.
автоматический бокс также пригодится когда мы работаем с Java.утиль.Тип коллекции. Когда мы хотим создать коллекцию примитивных типов, мы не можем непосредственно создать коллекцию примитивного типа , мы можем создать коллекцию только объектов. Например:
ArrayList<int> al = new ArrayList<int>(); // not supported
ArrayList<Integer> al = new ArrayList<Integer>(); // supported
al.add(45); //auto Boxing
Wrapper-Классы
каждый из 8 примитивных типов Java (byte,short,int,float,char,double,boolean, long) имеет отдельный класс оболочки, связанный с ними. Этот класс-оболочка имеет предопределенные методы для преформирования полезные операции с примитивными типами данных.
использование Wrapper-Классы
String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.
есть много полезных функций, которые предоставляют классы-оболочки. Проверьте документацию здесь
анбоксинг противоположно автоматическому боксу, где мы преобразуем объект класса оболочки обратно в его примитивный тип. Это делается автоматически 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 .
примитивные (необъектные) типы имеют там обоснование в эффективности.
примитивные типы int, boolean, double
являются непосредственными данными, тогда как Object
s являются ссылками. Следовательно, поля (или переменные)
int i;
double x;
Object s;
потребуется локальная память 4+8+8? где для объекта хранится только ссылка (адрес) на память.
использование оберток объектов Integer, Double
и другие, можно было бы ввести косвенность, ссылку на некоторый экземпляр Integer / Double в памяти кучи.
зачем нужен бокс?
это вопрос относительный характер. В будущем java планируется иметь возможность иметь ArrayList<int>
, подъем примитивных типов.
ответ: на данный момент ArrayList работает только для объекта, резервируя место для ссылки на объект и управляя сбором мусора. Отсюда универсального типа объектно детей. Поэтому, если кто-то хотел ArrayList значения с плавающей запятой, необходимые для обертывания double в Double объект.
здесь Java отличается от традиционного C++ своими шаблонами: c++ classes vector<string>, vector<int>
создаст два продукта компиляции. Java design пошел на наличие одного ArrayList.класс, не требующий для каждого типа параметра нового скомпилированного продукта.
поэтому без бокса к объекту нужно было бы компилировать классы для каждого вхождения типа параметра. В concreto: каждый класс коллекции или контейнера нужна версия для Object, int, double, boolean. Версия для Object будет обрабатывать все дочерние классы.
на самом деле, необходимость такой диверсификации уже существовала в Java SE для IntBuffer, CharBuffer, DoubleBuffer,... которые работают на int, char, double. Это было решено хакерским способом формирование эти источники из общего.
начиная с JDK 5, java добавила две важные функции: autoboxing и autounboxing. Автоупаковка - это процесс, для которого примитивный тип автоматически инкапсулируется в эквивалентную оболочку всякий раз, когда такой объект необходим. Вам не нужно явно создавать объект. Авто-распаковка - это процесс, при котором значение инкапсулированного объекта автоматически извлекается из оболочки типа, когда требуется его значение. Вам не нужно звонить такой метод, как сертификата от его закодированной формы() или doubleValue().
добавление autoboxing и автоматическ-распаковывать значительно упрощает написание алгоритмов, исключающ приманку вручную боксируя и распаковывая значений. Это также полезно избежать ошибок. Это также очень важно для дженерики, которые работают только с объектами. Наконец, autoboxing облегчает работу с Основа Коллекции.
почему у нас (ООН)бокс?
чтобы сделать написание кода, где мы смешиваем примитивы и их объектно-ориентированные (OO) альтернативы более удобными/менее подробными.
почему у нас есть примитивы и их альтернативы OO?
примитивные типы не являются классами (в отличие от C#), поэтому они не являются подклассами Object
и не может быть переопределен.
у нас есть примитивы типа int
для повышения производительности и Object
альтернативы, как Integer
для преимуществ программирования OO и в качестве второстепенной точки, чтобы иметь хорошее расположение для констант и методов полезности (Integer.Max_value и Integer.toString(int)
).
преимущества OO видны наиболее легко с дженериками (List<Integer>
), но не ограничиваются этим, например:
Number getMeSome(boolean wantInt) {
if (wantInt) {
return Integer.MAX_VALUE;
} else {
return Long.MAX_VALUE;
}
}
потому что они разные типы, и для удобства. Производительность, вероятно, является причиной наличия примитивных типов.
некоторые структуры данных могут принимать только объекты, без примитивных типов.
пример: ключ в HashMap.
см. этот вопрос для получения дополнительной информации:HashMap и int в качестве ключа
есть и другие веские причины, такие как поле "int" в базе данных, которое также может быть NULL. Int в Java не может быть null ; целочисленная ссылка может. Autoboxing и распаковывать обеспечивают с средством для того чтобы во избежание написать extraneous код в преобразованиях назад и далее.