Java中通配符泛型的实际用法

时间:2013-03-21 06:21:33

标签: java generics wildcard

我最近接受过Java考试,有很多关于Java中的通配符泛型的考试。但是,在实践中很少谈到它们的用法。我们应该何时使用它们?我们来看一个典型的用法:

void check(Collection<? extends Animal> list) {
  // Do something
}

文档说的是,此集合不允许向列表中添加任何元素。因此,基本上可以使用通配符将集合设置为只读。这是他们唯一的用法吗?那有什么实际需要吗?在过去的四年里,我参与了许多Java编程项目,但我没有看到任何项目会广泛使用像野外卡这样的功能。

因此,从实际的角度来看,是否有任何情况下,通配符泛型是不可避免和必要的?

3 个答案:

答案 0 :(得分:3)

  

所以,从实际的角度来看,是否有任何情况   通配符泛型是不可避免和必要的吗?

我不认为它们“不可避免且必要”,因为Java编译器无论如何都会删除它们。但是,在使用它们时,您可以在编译时获得更严格的类型检查,并避免使用类型转换。谁还想打字? :)

Guidelines for Wildcard Use

Type Erasure

答案 1 :(得分:1)

void check(Collection<? extends Animal> list) {
  list.add(new Animal()); // compile time error
  list.add(new Dog()); // compile time error. Dog is subclass of Animal class. 
}

Java开发了这样的泛型,因为不允许程序员编写任何他们想要的代码,否则如果允许的话,那么稍后他们会在运行时环境中发现混乱。

在编程的某个时候,你会得到一个场景,你的方法check不会在列表中添加元素但是想要读取这些元素。

您只能添加null个值。

答案 2 :(得分:0)

简而言之,你所说的是错误的。

它与“将集合设为只读”无关。

我们仍然可以在输入列表中添加元素,因为Collection确实声明了add(E)方法。

我认为通配符是直截了当的:你实际上想要约束输入类型,因为你的逻辑只适用于某种类型。

对于您的示例,您的检查可能使用Animal的某种方法

void check(Collection<? extends Animal> list) {
  // Do something
  for (Animal a : list) {
    a.checkAge();  // checkAge() is method of Animal
  }
}

如果没有? extends Animal,上面的代码将无效,因为传入列表可以是任何内容的集合(而不是动物)。

因此,我们希望确保传入集合为Collection或Collection等,以便我们的代码实际上有意义,因为我们从列表中检索元素并将元素视为Animal。