В чем разница между использованиемпротив SomeAbstract в дженериках Java - PullRequest
4 голосов
/ 15 июня 2011

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

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

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

class My_AbstractExtends<T extends SomeAbstract>

против

class My_Abstract<SomeAbstract>

EDIT

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

class My_ChildExtends extends My_AbstractExtends<ConcreteChildOfSomeAbstract>

против

class My_Child extends My_Abstract<ConcreteChildOfSomeAbstract>

Ответы [ 3 ]

8 голосов
/ 15 июня 2011

Я предполагаю, что вы говорите об использовании 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 является типичным примером для объяснения необходимости подстановочных знаков, потому что его природа как контейнера объектов делает его относительно простым для понимания, но относящиеся к ним правила применяются к любому универсальному типу. Я попытался объяснить это в общих чертах в этом ответе .

2 голосов
/ 15 июня 2011

Позволяет ссылаться на 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;
0 голосов
/ 16 июня 2011

Использование extends в объявлении универсального класса:

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

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

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

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

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