В чем разница между <? extends Object>
и <E extends Object>
?
Когда нужно использовать друг друга?
В чем разница между <? extends Object> и <E extends Object>?
Ответ 1
Вот некоторые отличия, которые мне сразу приходят в голову:
-
Ограничения параметра типа могут указывать несколько границ -
T extends A & B
, но с подстановочным знаком вы не можете указать несколько границ -? extends A & B
является недопустимым. -
Вы можете иметь нижние границы с подстановочным знаком -
? super A
действителен, но не с параметром типа -T super A
недействителен. -
Вы не можете использовать подстановочные рамки при создании родового типа. Вы должны использовать ограничения параметров типа.
-
Внутри метода, если вам нужна какая-то связь между параметрами параметров переданных аргументов, вам нужно использовать ограничения параметров типа. Например, вы хотите передать два параметризованных типа с одним и тем же параметром. Вы не можете сделать это с помощью подстановочных ограничений. Таким образом, в следующем объявлении метода будет использоваться два списка одного и того же типа, который расширяет
Number
.public <T extends Number> void merge(List<T> list1, List<T> list2) { }
Чтобы закончить, я добавлю некоторые моменты из Эффективной Java - Пункт 28: Используйте ограниченные подстановочные знаки для повышения гибкости API:
Для максимальной гибкости используйте типы подстановок для входных параметров, которые представляют производителей или потребителей. Если входной параметр является как производителем, так и потребителем, тогда типы подстановок не помогут вам: вам нужно точное совпадение типа, которое вы получаете без каких-либо подстановочных знаков.
Не используйте типы подстановочных знаков в качестве возвращаемых типов. Вместо того, чтобы предоставлять дополнительную гибкость для ваших пользователей, это заставит их использовать подстановочные типы в клиентском коде. Правильно используемые типы подстановочных знаков почти невидимы для пользователей класса. Они вызывают методы принятия параметров, которые они должны принимать, и отвергают те, которые они должны отклонить. Если пользователь класса должен думать о типах подстановочных знаков, возможно, что-то не так с API классов.
Литература:
Ответ 2
<? extends Object>
- это ограниченный подстановочный знак (неизвестный, который расширяет Object
, тогда как <E extends Object>
является ограниченным типом (E
требует параметра с параметрами, который расширяет Object
).
Большинство тонких различий ограниченных подстановочных знаков от параметризованной верхней границы:
-
Ограниченные подстановочные знаки нельзя использовать при создании классов Generic type, допускаются только типизированные параметры.
-
Ограниченные подстановочные знаки нельзя использовать в
Collection
, где требуется добавить элементы в коллекцию, так как это неизвестный тип, и коллекция не знает, какой тип он получает, следовательно, это не типа. -
Ограниченные подстановочные знаки не могут быть ограничены несколькими общими типами (границами).
Надеюсь, это поможет.
Ответ 3
Используйте E
, если вам нужно позже обратиться к типу. Используйте ?
, если вам больше не придется ссылаться на тип.
Ответ 4
В общем коде знак вопроса (?), называемый подстановочным знаком, представляет неизвестный тип. Подстановочный знак можно использовать в различных ситуациях: как тип параметра, поля или локальной переменной; иногда как возвращаемый тип (хотя лучше практика программирования более конкретна). Подстановочный знак никогда не используется в качестве аргумента типа для общего вызова метода, создания экземпляра универсального класса или супертипа. Для получения дополнительной информации проверьте this
Ответ 5
<E>
объявляет аргумент типа.
Его можно использовать только при создании общего типа или метода.
<? ...>
является подстановочным значением аргумента типа.
Вы можете использовать его только при создании закрытого родового типа.