2010-04-27 2 views
185

Почему дженерики в Java работают с классами, но не с примитивными типами?Почему Java Generics не поддерживает примитивные типы?

Например, это работает отлично:

List<Integer> foo = new ArrayList<Integer>(); 

, но это не допускается:

List<int> bar = new ArrayList<int>(); 
+0

int i = (int) new Object(); компилирует только штраф, хотя. –

ответ

194

Обобщение в Java является полностью время компиляции конструкта - компилятор превращает все общие использования в слепки к правильному типу. Это должно поддерживать обратную совместимость с предыдущими версиями JVM.

Это:

List<ClassA> list = new ArrayList<ClassA>(); 
list.add(new ClassA()); 
ClassA a = list.get(0); 

преобразуемые (примерно):

List list = new ArrayList(); 
list.add(new ClassA()); 
ClassA a = (ClassA)list.get(0); 

Таким образом, все, что используется в качестве дженерик должно быть конвертируемыми на объект (в данном примере get(0) возвращает Object) , а примитивные типы - нет. Поэтому они не могут использоваться в дженериках.

+0

Проясните, что это только для Java. – ChaosPandion

+31

В C# нет проблем с примитивными типами. – Danvil

+0

@ChaosPandion: сделано – thecoop

30

В Java дженерики работают так, как они это делают ... по крайней мере частично ... потому что они были добавлены к языку через несколько лет после того, как язык был разработан . Дизайнеры языка были с ограничениями в своих вариантах для дженериков, имея придумать дизайн, который был обратно совместим с существующим языком и библиотекой классов Java.

Другие языки программирования (например, C++, C#, Ada) позволяют использовать примитивные типы в качестве типов параметров для дженериков. Но обратная сторона этого заключается в том, что реализации таких языков для генериков (или типов шаблонов) обычно влекут за собой генерирование отдельной копии типичного типа для каждой параметризации типа.


1 - Причина дженерики не были включены в Java 1.0 было из-за нехватки времени. Они почувствовали, что им нужно быстро выпустить Java-язык, чтобы заполнить новую рыночную возможность, представленную веб-браузерами. Джеймс Гослинг заявил, что он хотел бы включить дженерики, если бы у них было время. Как бы выглядел язык Java, если бы это произошло, это догадка.

5

Для коллекций требуется тип, который имеет номер java.lang.Object. Базисы просто этого не делают.

+21

Я думаю, что вопрос здесь «почему». Почему дженерикам нужны объекты? Похоже, что консенсус состоит в том, что он имеет меньший выбор дизайна и больше подходит для обратной совместимости. На мой взгляд, если дженерики не могут обрабатывать примитивы, это дефицит функциональности. Как бы то ни было, все, что связано с примитивами, должно быть записано для каждого примитива: вместо Comparator у нас есть Integer.compare (int a, int b), Byte.compare (byte a, byte b) и т. Д. Это не решение ! –

+0

Да, дженерики над примитивными типами были бы обязательной функцией. Вот ссылка на предложение для него http://openjdk.java.net/jeps/218 – crow

1

В соответствии с Java Documentation переменные общего типа могут быть созданы только ссылочными типами, а не примитивными типами.

Предполагается, что это должно появиться на Java 10 под Project Valhalla.

В Brian Goetz бумаги на State of the Specialization

Существует excellent explanation о причине, по которой родовым не поддерживается для примитива. И, how it will be implemented в будущих выпусках Java.

Текущая стираемая реализация Java, которая создает один класс для всех эталонных экземпляров и не поддерживает примитивные экземпляры. (Это однородный перевод, и ограничение того, что дженерики Java могут распространяться только на ссылочные типы, связано с ограничениями однородного перевода по отношению к набору байт-кода JVM, который использует разные байткоды для операций над ссылочными типами по сравнению с примитивными типами.) Однако, стертые дженериков в Java обеспечивают и поведенческие parametricity (общие методы) и parametricity данных (сырые и подстановочные инстанциацию родовых типов.)

...

была выбрана однородная стратегия перевода, где общие переменные типа стираются до их границ, поскольку они включены в байт-код. Это означает, что независимо от того, является ли класс общим или нет, он все еще компилируется в один класс с тем же именем и подписи членов которого одинаковы. Безопасность типа проверяется во время компиляции, а среда исполнения неограниченна системой общего типа. В свою очередь это налагало ограничение на то, что дженерики могут работать только над ссылочными типами, поскольку объект является наиболее общим типом, и он не распространяется на примитивные типы.

Смежные вопросы