Ответ
Нет, напрямую использовать примитивные типы (int, char, boolean и т.д.) в Generics нельзя. Дженерики в Java работают только с ссылочными типами (классами). Это ограничение связано с механизмом стирания типов (type erasure), при котором информация о generic-типах удаляется во время выполнения.
Пример, который вызовет ошибку компиляции:
List<int> list = new ArrayList<>(); // Ошибка: Type argument cannot be of primitive type
Обходные пути и решения:
-
Использование классов-оберток (Boxing): Стандартный подход.
List<Integer> intList = new ArrayList<>(); intList.add(42); // Автоупаковка (auto-boxing) из int в Integer int value = intList.get(0); // Автораспаковка (auto-unboxing) обратно в int -
Специализированные библиотеки: Для высокопроизводительных сценариев, где накладные расходы на упаковку критичны, существуют сторонние библиотеки.
- GNU Trove: Предоставляет коллекции для примитивов (например,
TIntArrayList). - Eclipse Collections: Аналогично, предлагает
IntList,LongSetи т.д.
- GNU Trove: Предоставляет коллекции для примитивов (например,
Почему это важно? Использование Integer вместо int в коллекциях влечет за собой:
- Дополнительное потребление памяти (объект
Integervs. примитив). - Накладные расходы на упаковку/распаковку, что может влиять на производительность в tight loops.
Ответ 18+ 🔞
А, ну это же классика, блядь! Прямо в точку попали, ёпта. Сидишь такой, пишешь красивый дженерик-код, весь из себя архитектор, а тут — бац! — и вспоминаешь, что Java, сука, не всесильна.
Смотри, в чём прикол, а прикол в том, что дженерики — это такая хитрая жопа, которая существует только на этапе компиляции. А потом, во время выполнения, происходит стирание типов (type erasure), и все твои красивые List<String> и Map<Integer, Dog> превращаются в сырые List и Map. И компилятор, такой довольный, тебе подсказывает: «Чувак, бля, я тут подумал — а как я, сука, в этот общий котёл Object засуну твой примитивный int? Да никак, ёбаный насос! Он же не объект!»
Вот и выходит эта дичь:
List<int> list = new ArrayList<>(); // Ошибка: Type argument cannot be of primitive type
И компилятор прав, блядь! Он не мудак, он просто следует правилам. Примитивы — они как дикие звери, живут в стеке, быстрые и легковесные. А дженерики — это цивилизованный мир объектов в куче, где всё должно быть instanceof Object. И пути их, блядь, не пересекаются.
Так что же делать, если очень надо? Варианты есть, конечно.
-
Классы-обёртки (Boxing). Стандартный, дефолтный, всепоглощающий способ. Просто берёшь и оборачиваешь свою примитивную сущность в объектную тушку.
List<Integer> intList = new ArrayList<>(); intList.add(42); // Смотри-ка, магия! Компилятор сам заворачивает int в Integer (автоупаковка) int value = intList.get(0); // А тут сам разворачивает обратно (автораспаковка)Удобно? Ебать как удобно! Прозрачно. Но, понимаешь, за всё надо платить. Каждый такой
Integer— это отдельный объект в куче. Памяти жрёт больше. И эти постоянные упаковки-распаковки в цикле на миллион итераций... Ну, ты понял, производительность может накрыться медным тазом. -
Специализированные библиотеки для извращенцев. Если тебе реально насрать на память и каждый такт процессора на счету, то добро пожаловать в мир сторонних решений. Тут тебе и GNU Trove с его
TIntArrayList(список дляint, без всякихInteger!), и Eclipse Collections сIntList. Это уже серьёзные парни, они работают напрямую с массивами примитивов, обходя ограничения дженериков. Но, естественно, со своим API и зависимостями.
Итог, блядь, простой: для 95% случаев — юзай Integer, Double, Boolean и не парься. Автоупаковка — великая вещь. Но если пишешь какую-нибудь графическую или научную хуйню, где каждый байт и цикл на вес золота, — тогда уже лезь в дебри Trove. Выбор, как всегда, между удобством и скоростью.