Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wildcards in Generics: "? super T" works while "? extends T" does not?

My question is about generics in Java 7. Suppose we have such class hierarchy:

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

Just like in Java Generics Tutorial

Also we have a 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);
    }
}

And here is the code which uses that classes:

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   
    }

Question #1:

I have read here about these issues but there was simply like Cage<?>. But I tell the compiler <? extends Animal> so type T in Cage<T> will be any of subtypes of Animal type. So why it still gives a compile time error?

Question #2:

If I specify Cage<? super Animal> cage = ... instead of Cage<? extends Animal> cage = ... everything works fine and compiler doesn't say anything bad. Why in this case it works fine while in the example above it fails?

like image 756
maks Avatar asked Sep 24 '11 20:09

maks


1 Answers

The cage must be able to hold both types of animals. "super" says that - it says that the Cage must be able to hold all types of animals - and maybe some other things, too, because ? super Animal might be a superclass of Animal. "extends" says that it can hold some kinds of animals - maybe just Lions, for instance, as in:

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

which would be a valid statement, but obviously the lion cage won't hold butterflies, so

cage.add(new Butterfly());   

wouldn't compile. The statement

cage.add(new Lion());

wouldn't compile either, because Java here is looking at the declaration of the cage - Cage<? extends Animal> - not the object that's assigned to it right now (Cage<Lion>).

The best description of generics I know of is in O'Reilly's Java in a Nutshell. The chapter is free online - part 1 and part 2.

like image 121
Ed Staub Avatar answered Sep 29 '22 07:09

Ed Staub