Boxing и unboxing



В java 2 типа сущностей — примитивы и ссылочные типы. К первой группе относятся int, long, boolean и остальные типы с маленькой буквы. В таких переменных хранится само значение. Набор действий с примитивами ограничен, зато вычисления происходят с космической скоростью.



К ссылочным типам относится всё остальное: объекты, массивы, интерфейсы и тд. Такие переменные хранят указатель на участок памяти, где находится объект. Объекты занимают больше места, чем примитивы, зато функционал гораздо шире.



Работать с коллекциями приятнее, чем с массивами, поэтому в джава сделали костыль workaround для примитивных типов — классы-обёртки (Integer, Long, …) и боксинг/анбоксинг.



В целом это удобно, но появляются проблемы:



Неосознанный boxing/unboxing и лишняя трата памяти и времени

NPE в неожиданных местах

Неоднозначная работа с ==

Трудности по работе с массивами



Что происходит в коде выше?



Сигнатура метода asList выглядит так:



List<T> asList(T… a)



Метод ждёт на вход объекты ссылочных типов. В случае stringArr всё ок, передаются 4 ссылки на объект String, и создаётся список с 4 элементами.



Во второй части ситуация менее однозначная. Для массивов и коллекций не работает автоматическое приведение типов и боксинг/анбоксинг:



List<Child> не приводится автоматически к List<Parent>

Массив int не приводится автоматически к массиву Integer



В метод уже приходит ссылка — ссылка на массив примитивов. JVM всё устраивает, и она создаёт List из ссылок на массив.



Получится List<int[]>, в котором будет один элемент — ссылка на {1,2,3}. Массив с числом не сравнить, поэтому ответ на вопрос перед постом: true false



⭐️ Заметка 1: немного смуты здесь вносит var. Если писать целиком



List<Integer> res = Arrays.asList(intArray)



то компилятор сразу укажет на несоответствие типов



⭐️ Заметка 2: сигнатура contains выглядит так:



boolean contains(Object o)



Метод примет что угодно — строку, примитив (здесь выполнится боксинг) или экземпляр StringBuilder. Поэтому ошибок компиляции нет



Как получить нормальный список из массива примитивов?



var intList = Arrays.stream(intArray).boxed().collect(toList());



Закончу на оптимистичной ноте. В рамках Project Valhalla в JVM добавят три новых типа данных: value objects, primitive classes, specialized generics. В двух словах об этом не рассказать, но есть шанс, что через 10 лет код выше будет работать, как ожидается🤭