Wildcards in Java question
Given the following classes
class Creature {}
class Animal extends Creature {}
class Dog extends Animal {}
And the following lists
List<? super Animal> l1;
List<? extends Animal> l2;
Which of these commands will cause a compilation error?
1) l1.add(new Dog())
2) l1.add(null)
3) Object a = l1.get(0)
4) l2.add(new Dog())
5) Creature 开发者_JS百科c = l2.get(0))
I think it's four, because ? extends Animal
isn't necessarily a supertype of Dog
, but I'm not completely sure. An explanation would help a lot :)
Super and Extends
The line List<? super Animal> l1;
means that the list l1
can be instantiated to hold objects of a super-type of Animal
. Example: l1 = new LinkedList<Creature>();
The line List<? extends Animal> l2;
means that the list l2
can be instantiated to hold objects of a subtype of Animal
. Example: l2 = new LinkedList<Dog>();
Answers
Assuming that the lists are constructed.
1) The list l1
may be instantiated to hold any super-type of Animal
. Since Dog
is a subtype of any super-type of Animal
it can be casted implicitely. Compiles.
2) Compiles always. The specification of List
does not deny nulls. Runtime exception depends on the whether the list implementation allows null elements. LinkedList allows nulls.
3) Implicit casting to super-type (every object is an instance of class Object
) compiles always. Causes exception at runtime if the list is empty.
4) The add
method's signature for List<? extends Animal> l2
is l2.Add(? extends Animal)
. When we call l2.Add(new Dog())
the compiler can't be sure that the type ?
is a super-type of Dog
(since it doesn't know what ?
is, as we explicitely call the method using the List
interface and not through an implementation of List
), and therefore it must cause a compilation error.
From comments: "Note, though, that this issue has nothing to do with using an interface when referring to the container. The same compilation error would have occurred, when, say, ArrayList had been used in the declaration instead of lList." – Dirk
5) Assuming that the extra parenthesis is a mistake. Implicit casting to super-type compiles always. Creature
is a super-type of anything the list l2
can hold. Causes exception at runtime if the list is empty.
An image may help in understanding:
Also, see section 4.5.1 of the Java Language Specification, specially §4.5.1.1
精彩评论