Почему Java Generics не поддерживает примитивные типы? - PullRequest
212 голосов
/ 27 апреля 2010

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

Например, это прекрасно работает:

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

но это не разрешено:

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

Ответы [ 5 ]

220 голосов
/ 27 апреля 2010

Дженерики в 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);

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

33 голосов
/ 27 апреля 2010

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

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


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

6 голосов
/ 06 апреля 2018

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

public class Container<T> {

    private T data;

    public T getData() {
        return data;
    }
}

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

public class Container {

    private Object data;

    public Object getData() {
        return data;
    }
}

Компилятор отвечает за правильное приведение типов для обеспечения безопасности типов.

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

станет

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

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

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

Поскольку все примитивы не наследуются от " Object ", поэтому мы не можем его использовать как универсальный тип.

К вашему сведению: проект Valhalla пытается решить вышеуказанную проблему.

6 голосов
/ 27 апреля 2010

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

2 голосов
/ 18 декабря 2017

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

Это должно быть в Java 10 под Project Valhalla .

В Брайан Гетц документ о Состояние специализации

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

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

...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...