Java中的通配符问题

时间:2011-06-26 10:36:34

标签: java wildcard

鉴于以下课程

class Creature {}
class Animal extends Creature {}
class Dog extends Animal {}

以下列表

List<? super Animal> l1;
List<? extends Animal> l2;

这些命令中的哪一个会导致编译错误?

1) l1.add(new Dog())
2) l1.add(null)
3) Object a = l1.get(0)
4) l2.add(new Dog())
5) Creature c = l2.get(0))

我认为这是四,因为? extends Animal不一定是Dog的超类型,但我不完全确定。解释会有很多帮助:))

2 个答案:

答案 0 :(得分:5)

超级和延伸

List<? super Animal> l1;表示列表l1可以实例化,以保存{em>超类型 Animal的对象。示例:l1 = new LinkedList<Creature>();

List<? extends Animal> l2;表示列表l2可以实例化,以保存Animal子类型的对象。示例:l2 = new LinkedList<Dog>();

答案

假设列表已构建。

1)列表l1可以被实例化以保存任何超类型的Animal。由于Dog是任何超类型Animal的子类型,因此可以隐含地进行转换。编译。

2)总是编译。 List的规范并不否认空值。运行时异常取决于列表实现是否允许null元素。 LinkedList允许空值。

3)隐式转换为超类型(每个对象都是类Object的实例)总是编译。如果列表为空,则在运行时导致异常。

4)add List<? extends Animal> l2方法的签名为l2.Add(? extends Animal)。当我们调用l2.Add(new Dog())时,编译器无法确定类型?Dog的超类型(因为它不知道?是什么,因为我们使用List接口而不是通过List的实现来明确地调用该方法,因此它必须导致编译错误。

来自评论:“请注意,这个问题与引用容器时使用接口无关。发生相同的编译错误,例如ArrayList已经发生过在声明中使用而不是lList。“ - 德克

5)假设额外的括号是错误的。总是隐式转换为超类型编译。 Creature是列表l2可以容纳的任何内容的超类型。如果列表为空,则在运行时导致异常。

答案 1 :(得分:0)

图片可能有助于理解:

class diagram

另请参阅4.5.1 of the Java Language Specification部分,特别是§4.5.1.1