Почему нельзя объявить List<int> и что пишут вместо этого?
- Почему в дженериках нельзя использовать примитивы?
- Что такое автоупаковка?
- Чем List<Integer> хуже int[]?
Параметр дженерика может быть только ссылочным типом, поэтому пишут List<Integer> с автоупаковкой.
- Причина — стирание типов: в байткоде параметр становится Object
- Цена боксинга: объекты в куче, лишняя память и работа GC
А ещё Для больших объёмов чисел — int[], IntStream или специализированные коллекции
Подробно
Дженерики в Java реализованы через стирание типов: после компиляции параметр типа заменяется на его границу, обычно Object. Примитив int не является объектом, поэтому List<int> не компилируется.
Вместо него используют класс-обёртку List<Integer>. Компилятор сам превращает int в Integer при добавлении (автоупаковка, valueOf) и обратно при чтении (распаковка, intValue).
У этого есть цена: каждое число — отдельный объект в куче с заголовком, коллекция хранит ссылки, а не значения. На миллионах элементов это заметно по памяти и скорости, плюс нагрузка на сборщик мусора. Поэтому в горячем коде используют массивы примитивов, IntStream/LongStream и специализированные библиотеки коллекций примитивов.
Ловушки автоупаковки: NullPointerException при распаковке null, сравнение обёрток через ==, а также list.remove(1) у List<Integer> — удаляет элемент по индексу 1, а не значение 1.
Пример
List<Integer> nums = new ArrayList<>();
nums.add(5); // автоупаковка: Integer.valueOf(5)
int first = nums.get(0); // распаковка
nums.remove(Integer.valueOf(5)); // удалить значение 5, а не индекс
int sum = IntStream.rangeClosed(1, 1_000_000).sum(); // без боксингаЧто хотят услышать
- Дженерики работают только со ссылочными типами — используют обёртку.
- Связь со стиранием типов.
- Автоупаковка и её стоимость.
- Альтернативы для производительности и ловушки — плюс.
Частые ошибки
- Считать, что обёртка и примитив взаимозаменяемы без накладных расходов.
- Забывать про скрытый боксинг при вставке в List<Integer>.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Можно: List<int> допустим начиная с Java 8
- ✓Дженерики работают только со ссылочными типами — пишут List<Integer>
- ✗int нельзя хранить в коллекциях вообще — только массив int[], без обёрток и автоупаковки
- ✗List<int> работает, но без автоупаковки
Что спросят дальше
- Что такое стирание типов и при чём тут это ограничение?
- Когда вместо List<Integer> взять int[]?
Разбор темы
- Примитивы, обёртки и Integer cache
Восемь примитивов и их диапазоны, autoboxing, кэш Integer и ловушка ==, NPE при распаковке и цена боксинга.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.