Java noob: обобщение только для объектов?
Я новичок в Java. При кодировании карты<> я обнаружил, что объявление Map<int, int>
это синтаксическая ошибка в то время как Map<Integer, Integer>
все в порядке. Можно ли только в Java создавать экземпляры обобщений над типами объектов, а не примитивами? Если да, есть ли заметное снижение производительности при упаковке / распаковке примитивов?
4 ответа
Да, вы можете использовать только ссылочные типы для параметров универсального типа, и да, будет некоторое снижение производительности из-за упаковки / распаковки (что может быть выполнено автоматически по большей части).
Вот цитата из часто задаваемых вопросов по Java Generics:
Разрешены ли примитивные типы в качестве аргументов типа?
Нет. Только ссылочные типы могут использоваться в качестве аргументов типа. Параметризованный тип, такой как
List<int>
или жеSet<short>
незаконно Только эталонные типы могут использоваться для создания экземпляров универсальных типов и методов. ВместоList<int>
мы должны объявитьList<Integer>
используя соответствующий тип оболочки в качестве аргумента типа.[...] Обратите внимание, что отсутствие экземпляров примитивного типа влечет за собой снижение производительности. Autoboxing и -unboxing делают использование экземпляров универсальных типов упаковочных типов очень удобным и лаконичным в исходном коде. Но краткая запись скрывает тот факт, что за кулисами виртуальная машина создает и использует множество объектов-оболочек, каждый из которых должен быть выделен, а затем собран мусор. Более высокая производительность прямого использования значений примитивных типов не может быть достигнута с универсальными типами. Только обычный тип может обеспечить оптимальную производительность при использовании значений примитивного типа.
Если вам абсолютно необходима производительность, у Trove есть много структур данных, специально предназначенных для примитивных типов, но для большинства практических целей использование примитивных типов в штучной упаковке с классами Java Collections Framework должно дать более чем приемлемую производительность.
Смотрите также
- Effective Java 2nd Edition, Item 49: Предпочитайте примитивные типы коробочным типам
- Руководство по языку Java /Autoboxing
- Руководство по языку Java / Обобщения
- Учебные пособия по Java / Дженерики
Можно ли только в Java создавать экземпляры обобщений над типами объектов, а не примитивами?
правильный.
Если да, есть ли заметное снижение производительности при упаковке / распаковке примитивов?
Да, есть.
Смотрите подробное описание здесь: http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html
1) Да, дженерики Java работают только с объектами. Это из-за того, как они реализованы, что происходит посредством стирания типов - по сути, после того, как он скомпилирован в байт-код, все универсальные типы заменяются на Object
- это было сделано для того, чтобы java-генерики могли работать без изменения базовой JVM/ байт-кода (плохое решение, imo).
2) Да, будет штраф за бокс / распаковку; Боюсь, этого не избежать.
Как уже отмечали другие, при использовании классов-оболочек для примитивов снижается производительность. И хотя стоимость не очень заметна, если вам ДЕЙСТВИТЕЛЬНО нужно дополнительное повышение производительности, вы можете просто создать собственные подклассы для класса List, по одному для каждого типа примитива (их не много, так что это не проблема) и просто переопределить методы которые помещают и получают значения в списке и ограничивают их принятием каждого примитива. Это приведет к увеличению производительности и сохранит многословность общего списка кода.