Вопрос-ответ

Java Generics (Wildcards)

Обобщения Java (подстановочные знаки)

У меня есть пара вопросов об общих подстановочных знаках в Java:


  1. В чем разница между List<? extends T> и List<? super T>?


  2. Что такое ограниченный подстановочный знак и что такое неограниченный подстановочный знак?


Переведено автоматически
Ответ 1

В вашем первом вопросе <? extends T> и <? super T> являются примерами ограниченных подстановочных знаков. Неограниченный подстановочный знак выглядит как <?> и в основном означает <? extends Object>. Это в общих чертах означает, что generic может быть любого типа. Ограниченный подстановочный знак (<? extends T> или <? super T>) накладывает ограничение на тип, говоря, что он либо должен расширять определенный тип (<? extends T> известен как верхняя граница), либо должен быть предком определенного типа (<? super T> известен как нижняя граница).

В руководствах по Java есть несколько довольно хороших объяснений обобщений в статьях Подстановочные знаки и с подстановочными знаками интереснее.

Ответ 2

Если у вас есть иерархия классов A, B это подкласс A, а C и D оба являются подклассами B, как показано ниже

class A {}
class B extends A {}
class C extends B {}
class D extends B {}

Затем

List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();

List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile

public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}

public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}

Ограниченный подстановочный знак подобен тому, что ? extends B где B - это некоторый тип. То есть тип неизвестен, но к нему можно добавить "привязку". В этом случае он ограничен некоторым классом, который является подклассом B.

Ответ 3

У Джоша Блоха также есть хорошее объяснение, когда использовать super и extends в этом видео-докладе о Google io, где он упоминает мнемонику производителя extends для super потребителя.

Из слайдов презентации:


Предположим, вы хотите добавить массовые методы в Stack<E>


void pushAll(Collection<? extends E> src);


– src является разработчиком E


void popAll(Collection<? super E> dst);


– dst является пользователем E


Ответ 4

Могут возникнуть ситуации, когда вам захочется ограничить типы, которые разрешено передавать в параметр типа. Например, метод, который работает с numbers, может захотеть принимать только экземпляры Number или его подклассов. Для этого и нужны параметры ограниченного типа.

Collection<? extends MyObject> 

означает, что он может принимать все объекты, которые имеют отношение IS- A к MyObject (т. Е. Любой объект, являющийся типом MyObject, или мы можем сказать, любой объект любого подкласса MyObject) или объект класса MyObject.

Например:

class MyObject {}

class YourObject extends MyObject{}

class OurObject extends MyObject{}

Затем,

Collection<? extends MyObject> myObject; 

будет принимать только MyObject или дочерние элементы MyObject (т.е. Любой объект типа OurObject, YourObject или MyObject, но не любой объект суперкласса MyObject).

java generics