6

我最近参加了一次 Java 考试,其中有很多关于 Java 通配符泛型的部分。然而,关于它们在实践中的用法却很少提及。我们什么时候应该使用它们?我们来看一个典型的用法:

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

文档所说的,这个集合不允许向列表中添加任何元素。所以基本上通配符可用于使集合成为只读。这是他们唯一的用途吗?有实际需要吗?在过去的四年里,我参与了很多 Java 编程项目,但我还没有看到任何项目会广泛使用通配符这样的特性。

那么,从实践的角度来看,是否存在通配符泛型是不可避免和必要的情况呢?

4

3 回答 3

3

那么,从实践的角度来看,是否存在通配符泛型是不可避免和必要的情况呢?

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

通配符使用指南

类型擦除

于 2013-03-21T07:04:44.817 回答
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值。

于 2013-03-21T06:33:10.120 回答
0

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

它与“使集合成为只读”无关。

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

我认为通配符很简单:您实际上想要限制输入类型,因为您的逻辑仅对某些类型是合理的。

对于您的示例,您的支票可能使用某种动物方法

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

没有? extends Animal,上面的代码将不起作用,因为传入的列表可以是任何东西的集合(不是动物)。

因此,我们要确保传入集合到 Collection 或 Collection 等,以便我们的代码在我们从列表中检索元素并将元素视为 Animal 时真正有意义。

于 2013-03-21T06:35:43.777 回答