Почему мы используем 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); 

    } 
}