
Что такое
autoboxing
?Автоупаковка — это механизм неявной инициализации объектов классов-оберток (Byte, Short, Character, Integer, Long, Float, Double) значениями соответствующих им исходных примитивных типов (соотв.
byte
,short
,char
,int
,long
,float
,double
), без явного использования конструктора класса.Автоупаковка происходит при прямом присвоении примитива — классу-обертке (с помощью оператора "
=
"), либо при передаче примитива в параметры метода (типа "класса-обертки"). Автоупаковке в "классы-обертки" могут быть подвергнуты как переменные примитивных типов, так и константы времени компиляции (литералы иfinal
-примитивы). При этом литералы должны быть синтаксически корректными для инициализации переменной исходного примитивного типа.Автоупаковка переменных примитивных типов требует точного соответствия типа исходного примитива — типу "класса-обертки". Например, попытка автоупаковать переменную типа
byte
вShort
, без предварительного явного приведенияbyte->short
вызовет ошибку компиляции.Автоупаковка констант примитивных типов допускает более широкие границы соответствия. В этом случае компилятор способен предварительно осуществлять неявное расширение/сужение типа примитивов. Преобразование происходит в два этапа:
неявное расширение(сужение) исходного типа примитива до типа примитива соответствующего классу-обертке (для преобразования
int->Byte
, сначала компилятор неявно сужаетint
вbyte
)автоупаковку примитива в соотвествующий "класс-обертку" (компилятор автоупаковывает
byte->Byte
). однако в этом случае существуют два дополнительных ограничения:присвоение примитива — "обертке" может производится только оператором "
=
" (нельзя передать такой примитив в параметры метода, без явного приведения типов)тип левого операнда не должен быть старше чем
Character
, тип правого не дожен старше чемint
, (допустимо расширение/сужениеbyte <-> short
,byte <-> char
,short <-> char
и только сужениеbyte <- int
,short <- int
,char <- int
, все остальные варианты требуют явного приведения типов)
Дополнительная особенность целочисленных "классов-оберток" созданных автоупаковкой констант в диапазоне -128 +127 , в то что они кэшируются JVM. Потому такие обертки с одинаковыми значениями будут являтся ссылками на один объект.
Зачем используется
autoboxing
?Я процитирую лекцию:
Насколько ты помнишь, в Java есть как типы, унаследованные от класса
Object
, так и примитивные типы. Но, как оказалось, такая удобная вещь как коллекции и generic’и могут работать только с типами, унаследованными отObject
.Альтернативы
autoboxing
?Не нашел ответа, но запостил на StackOverFlow.
Исходя из этой дискуссии, получается, что альтернатива
autoboxing
`у это использование примитивных типов, так как использовниеautoboxing
`a снижает производительность. Вывод: использоватьautoboxing
только там где это необходимо.Написана статья про
Autoboxing
: Autoboxing: Traps and AdvantagesТипы-обертки для примитивных типов
mutable
илиimmutable
?Immutable
, так как примитивные объекты тожеimmutable
. Чтобы работать как сMutable
типом есть классMutableInteger
, и.т.д.Как примитивные типы приводятся к непримитивным аналогам?
На этот и последующий вопросы хорошо отвечает вот эта статья: Автоупаковка и распаковка в Java
Это заключение из нее: автоупаковка является механизмом для скрытого преобразования примитивных типов данных в соответствующие классы-оболочки (объекты). Компилятор использует метод
valueOf()
чтобы преобразовать примитивные типы в объекты, а методыIntValue()
,doubleValue()
и т.д., чтобы получить примитивные типы из объекта (то есть обратное преобразование). Автоупаковка преобразует логический типboolean
вBoolean
,byte
вByte
,char
вCharacter
,float
вFloat
,int
вInteger
,long
вLong
,short
вShort
. Распаковка происходит в обратном направлении.Как непримитивные типы приводятся к примитивным?
Выше ответил.
Как сравниваются примитивные и непримитивные типы?
В лекции это подробно рассматривается, но я нашел так скажем тоже самое, но другими словами.
В Java есть два способа сравнивать объекты на равенство,
==
и методequals()
.==
используется для примитивных типов. Для объектов «==
» это исключительно сравнение ссылок. Для остальных случаев нужно использовать методequals()
. Кроме того методhashCode()
служит (в теории) для той же цели. Хорошим тоном считается, если вы переопределилиequals()
иhashCode()
. После инициализации неких объектов a и b должно выполняться правило:Если выражение
a.equals(b)
вернет true, тоa.hashCode()
должен быть равенb.hashCode()
.Всегда ли создается новый объект при операции
autoboxing
?Это в лекциях есть:
Когда мы присваиваем переменной типа Integer значение типа
int
, при этом вызывается методInteger.valueOf
: функцияvalueOf
не всегда создает новый объект типа Integer. Она кэширует значения от -128 до 127.Если передаваемое значение выходит за эти пределы, то новый объект создается, а если нет, то нет.
Если мы пишем
new Integer()
, то гарантированно создается новый объект. Если мы вызываемInteger.valueOf()
, явно или приautoboxing
, то этот метод может вернуть для нас как новый объект, так и отдать объект из кэша, если переданное число лежит в диапазоне от -128 до 127.Как работает кэширование при операции
autoboxing
?Ответил в вопросе выше, на всякий случай создал вопрос на StackOverFlow, но там отвечают тоже самое
Для каких типов и/или значений работает кэширование?
В восьмом вопросе. Если у кого – то есть соображения на тему трех последних вопросов, то напишите в комментариях.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
С (byte… args) тоже не в приоритете.