Подтвердить что ты не робот

В чем разница между <? extends Object> и <E extends Object>?

В чем разница между <? extends Object> и <E extends Object>? Когда нужно использовать друг друга?

4b9b3361

Ответ 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> объявляет аргумент типа.
Его можно использовать только при создании общего типа или метода.

<? ...> является подстановочным значением аргумента типа.
Вы можете использовать его только при создании закрытого родового типа.