我最近接受过Java考试,有很多关于Java中的通配符泛型的考试。但是,在实践中很少谈到它们的用法。我们应该何时使用它们?我们来看一个典型的用法:
void check(Collection<? extends Animal> list) {
// Do something
}
文档说的是,此集合不允许向列表中添加任何元素。因此,基本上可以使用通配符将集合设置为只读。这是他们唯一的用法吗?那有什么实际需要吗?在过去的四年里,我参与了许多Java编程项目,但我没有看到任何项目会广泛使用像野外卡这样的功能。
因此,从实际的角度来看,是否有任何情况下,通配符泛型是不可避免和必要的?
答案 0 :(得分:3)
所以,从实际的角度来看,是否有任何情况 通配符泛型是不可避免和必要的吗?
我不认为它们“不可避免且必要”,因为Java编译器无论如何都会删除它们。但是,在使用它们时,您可以在编译时获得更严格的类型检查,并避免使用类型转换。谁还想打字? :)
答案 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。