Почему мы используем автобоксинг и распаковку в Java?
Autoboxing-Это автоматическое преобразование, которое делает компилятор Java между примитивными типами и соответствующей им оболочкой объекта занятия. Например, преобразование int в целое число, double в a Двойной и так далее. Если преобразование идет в другую сторону, это называется распаковка.
Так зачем нам это нужно и почему мы используем автобоксинг и распаковку в Java?
7 ответов:
требуется некоторый контекст, чтобы полностью понять основную причину этого.
примитивы против классов
примитивные переменные в Java содержат значения (целое число, двоичное число с плавающей запятой двойной точности и т. д.). Потому что эти значения могут иметь разную длину, переменные, содержащие их, также могут иметь разную длину (рассмотрим
float
иdouble
).С другой стороны, класс переменные содержат ссылки в случаях. Ссылки обычно реализуются как указатели (или что-то очень похожее на указатели) на многих языках. Эти вещи обычно имеют одинаковый размер, независимо от размеров экземпляров, на которые они ссылаются (
Object
,String
,Integer
, etc).это свойство переменных класса делает ссылки, которые они содержат заменимые (в определенной степени). Это позволяет нам делать то, что мы называем замена: вообще говоря, использовать экземпляр определенного типа в качестве экземпляра другого, связанного типа (использовать
String
какObject
, например).примитивные переменные не заменимый точно так же, ни друг с другом, ни с
Object
. Наиболее очевидной причиной этого (но не единственной) является их разница в размерах. Это делает примитивные типы неудобными в этом отношении, но мы все еще нуждаемся в них язык (по причинам, которые в основном сводятся к производительности).дженерики и стирание типа
универсальные типы-это типы с одним или несколькими параметры типа (точное число называется generic arity). Например,определение универсального типа
List<T>
имеет параметр типаT
, который может бытьObject
(производства конкретного типаList<Object>
),String
(List<String>
),Integer
(List<Integer>
) и так на.универсальные типы намного сложнее, чем не универсальные. Когда они были введены в Java (после его первоначального выпуска), чтобы избежать внесения радикальных изменений в JVM и, возможно, нарушения совместимости со старыми двоичными файлами,создатели Java решили реализовать универсальные типы наименее инвазивным способом: все конкретные типы
List<T>
фактически компилируются в (двоичный эквивалент)List<Object>
(для других типов, может быть что-то кромеObject
, но вы получите точку). в этом процессе теряется общая информация о параметрах arity и type, вот почему мы называем его стирания типа.соединяя их вместе
теперь проблема заключается в сочетании вышеуказанных реалий: если
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
, aFloat
Сfloat
и так далее, называется бокс. Обратное называется анбоксинг. Потому что каждый раз, когда вы хотите использовать их какObject
неудобно, есть случаи, когда язык делает это автоматически - это называется автоупаковка.
Автомобильный Бокс и используется для преобразования примитивных типов данных в объекты класса-оболочки. Класс-оболочка предоставляет широкий диапазон функций, которые должны выполняться на примитивных типах. Наиболее распространенный пример:
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.
есть много полезных функций, которые предоставляют классы-оболочки. Проверьте документацию здесь
анбоксинг является противоположностью 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 .
примитивные (не объектные) типы имеют там обоснование в эффективности.
примитивные типы
int, boolean, double
являются непосредственными данными, тогда какObject
s-это ссылки. Следовательно, поля (или переменные)int i; double x; Object s;
потребуется локальная память 4+8+8? где для объекта хранится только ссылка (адрес) на память.
использование обертки объекта
Integer, Double
и другие, можно было бы ввести косвенность, ссылку на некоторый экземпляр Integer / Double в куче памяти.зачем нужен бокс?
это вопрос относительный характер. В будущем java планируется иметь возможность иметь
ArrayList<int>
, подъем примитивных типов.ответ: На данный момент ArrayList работает только для объекта, резервируя место для ссылки на объект и управляя сборкой мусора аналогичным образом. Отсюда универсального типа являются дочерними объектами. Так что если кто-то хотел ArrayList значения с плавающей запятой, нужно было обернуть двойной в двойной объект.
здесь Java отличается от традиционного C++ своими шаблонами: c++ classes
vector<string>, vector<int>
создаст два продукта компиляции. Дизайн Java пошел на наличие одного ArrayList.класс, не требующий для каждого типа параметра нового скомпилированного продукта.поэтому без бокса для объекта нужно было бы скомпилировать классы для каждого вхождения типа параметра. В concreto: каждый класс коллекции или контейнера будет нужна версия для объекта, int, double, boolean. Версия для объекта будет обрабатывать все дочерние классы.
фактически, необходимость в такой диверсификации уже существовала в Java SE для IntBuffer, CharBuffer, DoubleBuffer,... которые работают на int, char, double. Это было решено хакерским способом формирование эти источники из общего.
начиная с JDK 5, java добавила две важные функции: autoboxing и autounboxing. Автоупаковка - это процесс, для которого примитивный тип автоматически инкапсулируется в эквивалентную оболочку всякий раз, когда такой объект необходим. Вам не нужно явно создавать объект. Авто-распаковка - это процесс, при котором значение инкапсулированного объекта автоматически извлекается из оболочки типа, когда требуется его значение. Вам не нужно звонить такой метод, как сертификата от его закодированной формы() или doubleValue().
добавление автобоксинга и автоматической распаковки значительно упрощает написание алгоритмов, устраняя приманку вручную бокс и распаковку значений. Это также полезно для избежать ошибок. Это тоже очень важно для дженерики, которые работают только на объекты. Наконец, автобоксинг облегчает работу с Collections Framework.
почему у нас есть (ООН)бокс?
чтобы сделать написание кода, где мы смешиваем примитивы и их объектно-ориентированные (OO) альтернативы более удобными/менее подробными.
почему у нас есть примитивы и их альтернативы OO?
примитивные типы не являются классами (в отличие от C#), поэтому они не являются подклассами
Object
и не может быть переопределен.у нас есть примитивы типа
int
для повышения производительности иObject
альтернативы, какInteger
для преимуществ программирования OO и как второстепенный момент, чтобы иметь хорошее расположение для служебных констант и методов (целое число.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 ; целочисленная ссылка может. Автобоксинг и распаковка обеспечивают возможность избежать написания постороннего кода в обратном и обратном преобразованиях. далее.