В чем разница между использованием <? расширяет SomeAbstract> против SomeAbstract в обобщениях Java

Я перехожу на Java из DotNet, и эта идея о расширении является новой.

Я видел несколько постов, которые полностью объясняют использование List<? extends SomeAbstract> против List<? super SomeAbstract> против List<SomeAbstract>, но я предполагаю, что нет никакой разницы между использованием и не использованием расширений в дженериках.

Это правда? Изменится ли ответ, если использовать абстрактный класс в качестве родителя?

class My_AbstractExtends<T extends SomeAbstract>

против

class My_Abstract<SomeAbstract>

РЕДАКТИРОВАТЬ

Создает дочерние классы следующим образом

class My_ChildExtends extends My_AbstractExtends<ConcreteChildOfSomeAbstract>

против

class My_Child extends My_Abstract<ConcreteChildOfSomeAbstract>

3 ответа

Решение

Я предполагаю, что вы говорите об использовании extends в объявлениях параметров типа. В таком случае:

class My_Abstract<T extends SomeAbstract>

имеет параметр ограниченного типа, называемый T это должно быть SomeAbstract или какой-то его подтип.

class My_Abstract<SomeAbstract>

имеет неограниченный параметр типа SomeAbstract это может быть что угодно. Обратите внимание, что SomeAbstract больше не относится к фактическому типу SomeAbstract что первый пример использует вообще!

Чтобы расширить это: представьте, было ли второе объявление class My_Abstract<T>, T явно есть параметр типа, а не фактический тип. Но это не должно называться T... это можно назвать E или же Bob или же SomeAbstract, Во всех этих случаях это все еще просто параметр типа... фактический тип никогда не может туда идти, и при этом это не имеет никакого смысла (весь смысл параметра типа в том, что он НЕ ссылается на конкретный тип, но вместо этого позвольте другим типам быть помещенными в его место, когда экземпляры класса созданы).

В коде, который вы редактировали, измените My_Childдекларация

class My_Child extends My_Abstract<Object>

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

Это становится действительно длинным, но я также хочу отметить, что все это в основном не связано с первой половиной вашего вопроса. Подстановочные знаки, как ? extends SomeAbstract а также ? super SomeAbstract не используются в объявлениях параметров типа (например, используемых при определении универсального класса), они в основном используются для параметров метода. List Типичный пример для объяснения необходимости подстановочных знаков, потому что его природа как контейнера объектов делает его относительно простым для понимания, но относящиеся к ним правила применяются к любому универсальному типу. Я попытался объяснить это в общих чертах в этом ответе.

Это позволяет вам ссылаться на T в других местах.

public class A<T extends SomeClass>{
    public A(T x){this.x=x;}
    public T x;
}

Тогда пользователи вашего класса могут использовать свой оригинальный тип вместо того, чтобы использовать SomeClass.

MyObject x = new A<MyObject>(new MyObject()).x;

С помощью extends в объявлении универсального класса:

  1. Ограничивает типы, которые могут использоваться в качестве параметра, теми типами, которые происходят от расширенного класса.
  2. Позволяет универсальному классу вызывать методы, объявленные в расширенном классе.

'?' Ключевое слово используется в методах, когда рассматриваемый код не заботится о конкретном типе параметра типа, а заботится только о его нижней (расширяемой) или верхней (супер) границе.

Википедия объясняет сетевые эффекты различных конструкций очень прагматично.

Чтобы понять, почему для определения универсальных элементов требуется несколько различных конструкций, вам нужно прочитать о ковариации и контравариантности, которые являются теоретическими названиями правил для безопасности статических типов в присутствии универсальных шаблонов.

Другие вопросы по тегам