Почему Java Generics не поддерживает примитивные типы?

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

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

List foo = new ArrayList(); 

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

 List bar = new ArrayList(); 

Генераторы в Java – это полностью компиляция – компилятор превращает все общие применения в приведения в правильный тип. Это должно поддерживать обратную совместимость с предыдущими версиями JVM.

Эта:

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

превращается в (грубо):

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

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

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

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


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

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

В java generics реализованы с помощью «Стирания типа» для обратной совместимости. Все общие типы преобразуются в Object во время выполнения. например,

 public class Container { private T data; public T getData() { return data; } } 

будет отображаться во время выполнения,

 public class Container { private Object data; public Object getData() { return data; } } 

компилятор несет ответственность за обеспечение надлежащего приведения, чтобы обеспечить безопасность типа.

 Container val = new Container(); Integer data = val.getData() 

станет

 Container val = new Container(); Integer data = (Integer) val.getData() 

Теперь возникает вопрос, почему «Объект» выбирается как тип во время выполнения?

Ответ. Объект – это суперclass всех объектов и может представлять любой пользовательский объект.

Поскольку все примитивы не наследуются от « Объекта », поэтому мы не можем использовать его как общий тип.

FYI: Проект Valhalla пытается решить вышеуказанный вопрос.

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

Предполагается, что он будет представлен на Java 10 в рамках проекта Valhalla .

В статье Брайана Гетца о состоянии специализации

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

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

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

Interesting Posts

Как я могу предотвратить сбой node.js? try-catch не работает

В каких сценариях замораживание объектов WPF значительно повышает производительность?

Есть ли способ выполнить круговое смещение бита в C #?

Как развернуть mutiple web-приложение в tomcat, которое будет работать на разных портах?

Создает ли новый формат SSD правильное выравнивание разделов?

Android: AsyncTask vs Service

Разгрузка classов в java?

Когда я должен явно использовать указатель `this`?

Как добавить поддержку C ++ 11 в компилятор Code :: Blocks?

Inno Setup – Выбор языка с помощью VCL Styles

Изменение цвета панели действий программно более одного раза

когда статическая переменная загружается в java, время выполнения или время компиляции?

jQuery переопределить отображение сообщения об ошибке проверки по умолчанию (Css) Всплывающее / всплывающее окно

Как открыть уже открытый файл с помощью .net StreamReader?

В PowerPoint существует ли способ создания печатной версии анимированного слайда?

Давайте будем гением компьютера.