Java Generics - <int> to <Integer>

На пути к обучению Java Generics я застрял в определенной точке.
Было написано: " Java Generics работает только с объектами, а не с примитивными типами".

e.g

 Gen<Integer> gen=new Gen<Integer>(88);     // Works Fine ..  

Но с примитивными типами, такими как int, char и т.д.

 Gen<int> gen=new Gen<int>(88) ;    // Why this results in compile time error 

Я хочу сказать, так как java generics имеет функцию автоматического бокса и распаковки, то почему эта функция не может применяться, когда мы объявляем определенный тип для нашего класса?

Я имею в виду, почему Gen<int> не автоматически преобразуются в Gen<Integer>?

Пожалуйста, помогите мне устранить это сомнение.
Спасибо.

Ответ 1

Autoboxing не говорит, что вы можете использовать int вместо Integer. Autoboxing автоматизирует процесс бокса и распаковки. Например. Если мне нужно сохранить некоторый примитивный int в коллекцию, мне не нужно создавать объект wrpper вручную. Его позаботился Java-компилятор. В приведенном выше примере вы создаете экземпляр общего объекта, который имеет тип Integer. Этот общий объект по-прежнему отлично работает с int, но объявление int как общего типа неверно. Дженерики разрешают только ссылки на объекты не примитивы.

Ответ 2

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

Ответ 3

Простое объяснение: Generics определяются таким образом.

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

С непримитивами компилятор должен будет решить, следует ли создавать или использовать inbox/outbox, он должен иметь дополнительные правила проверки (extends и & не имеет смысла с примитивами, если a ? включают примитивы, да или нет? и т.д.) и должны обрабатывать преобразования типов (предположим, что вы параметризируете коллекцию с помощью long и добавляете int...?)

Хорошая причина с точки зрения программистов: операции с плохой производительностью остаются видимыми! Разрешающие примитивы в качестве аргументов типа потребуют скрытого автобоксинга (inboxing for store, outboxing для операций чтения. Входящие могут создавать новые объекты, которые дороги. Люди ожидают быстрых операций, если они параметризуют общий класс с примитивами, но наоборот. p >

Ответ 4

Это очень хороший вопрос.

Как вы и предполагали, абстракция, несомненно, может быть расширена до параметров типа и сделана ими прозрачной для программиста. Фактически, это то, что делают большинство современных языков JVM (конечно, статически типизированные). Примеры включают Scala, Цейлон, Котлин и т.д.

Вот как выглядит ваш пример в Scala:

val gen: Gen[Int] = new Gen[Int](80)

Int - это просто обычный класс, как и другие классы. Нет никакого различия между примитивными объектами.

Что касается того, почему люди Java не делали этого... Я действительно не знаю причину, но я полагаю, что такая абстракция не соответствовала бы существующей спецификации Java без чрезмерного злоупотребления семантикой (или не жертвуя обратной совместимостью, который, безусловно, не является жизнеспособным вариантом).