Подстановочные знаки в Generics: «супер T» работает, а «расширяет T» не? - PullRequest
5 голосов
/ 25 сентября 2011

Мой вопрос о дженериках в Java 7. Предположим, у нас есть такая иерархия классов:

interface Animal {}    
class Lion implements Animal {}    
class Butterfly implements Animal {}

Так же, как в Учебное пособие по Java Generics

Также у нас естьclass

class Cage<T> {
    private List<T> arr = new ArrayList<>();
    public void add(T t) {
        arr.add(t);
    }
    public T get() {
        return arr.get(0);
    }
}

А вот код, который использует эти классы:

public static void main(String[] args) {
        Cage<? extends Animal> cage = new Cage<>();
        Animal a = cage.get(); //OK
        cage.add(new Lion()); //Compile-time error
        cage.add(new Butterfly()); //Compile-time error   
    }

Вопрос № 1:

Я прочитал здесь оэти проблемы, но были просто как Cage<?>.Но я говорю компилятору <? extends Animal>, поэтому тип T в Cage<T> будет любым из подтипов типа Animal.Так почему же все равно выдается ошибка времени компиляции?

Вопрос № 2:

Если я укажу Cage<? super Animal> cage = ... вместо Cage<? extends Animal> cage = ..., все будет работать нормально, и компилятор не скажет ничего плохого.Почему в этом случае он работает нормально, а в приведенном выше примере не работает?

1 Ответ

6 голосов
/ 25 сентября 2011

Клетка должна быть в состоянии содержать обоих типов животных.«супер» говорит, что - это говорит о том, что Клетка должна быть способна содержать всех животных - и, возможно, некоторые другие вещи, потому что ? super Animal может быть суперклассом Animal.«extends» говорит, что он может содержать некоторых видов животных - возможно, просто львов, например, как в:

Cage<? extends Animal> cage = new Cage<Lion>();

, что будет правильным утверждением, но, очевидно, клетка льване будет держать бабочек, поэтому

cage.add(new Butterfly());   

не скомпилируется.Оператор

cage.add(new Lion());

также не будет компилироваться, потому что здесь Java смотрит на объявление клетки - Cage<? extends Animal>, а не на объект, который ей назначен прямо сейчас (Cage<Lion>).

Лучшее описание дженериков, о которых я знаю, содержится в Java О'Рейли в двух словах .Глава бесплатна онлайн - часть 1 и часть 2 .

...