我将向您展示两种仿制品声明。在part1中,我在List上使用泛型上边界声明如下:
List<? extends Animal> totList = new ArrayList<Animal>();
但如果您尝试将Animal对象添加到列表中,则会抛出如下错误:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method add(capture#1-of ? extends Animal) in the type List<capture#1-of ? extends Animal> is not applicable for the arguments (Animal)
at GenericsType.main(GenericsType.java:39)
但是在Part2中,如果我以下面的格式在泛型类中声明列表,则在将(Animal对象)或(Animal对象的子类)添加到列表时不会抛出任何错误。
class GenericAnimal<T extends Animal>
{
List<T> genList = new ArrayList<T>();
}
为什么在part2中,它没有抛出错误,两种声明风格之间有什么区别。
示例代码:
1.Animal.java
public class Animal {
private String name;
private int height;
public void animalJump()
{
if(height>100)
{
System.out.println(name+" with height-"+height+" can JUMP");
}
else
System.out.println(name+" with height-"+height+" cannot jump");
}
public void setName(String name) {
this.name = name;
}
public void setHeight(int height) {
this.height = height;
}
public Animal(String name, int height) {
setName(name);
setHeight(height);
}
}
2.GenericsType.java
import java.util.*;
import Animal;
import Animal.Cannine;
import Animal.Feline;
import Animal.Feline.Cat;
import Animal.Cannine.Dog;
public class GenericsType {
public static List<? extends Animal> totList = new ArrayList<Animal>();
public static void processAllfunc1()
{
for(Animal a : totList)
{
a.animalJump();
}
}
public static void main(String args[])
{
// Part 1
totList.add(new Animal("Animal1",21)); // Error: Unresolved compilation problem:
processAllfunc1();
// Part 2
GenericAnimal<Animal> genericanimal = new GenericAnimal<Animal>();
genericanimal.genList.add(new Animal("Animal2",22)); // No Error, why?
genericanimal.genList.add(new Cat("Cat4",204)); // No Error for Cat also, why?
genericanimal.processAllfunc2();
}
}
3.GenericAnimal.java
public class GenericAnimal<T extends Animal> {
public List<T> genList = new ArrayList<T>();
public void processAllfunc2() {
for (T a : genList) {
a.animalJump();
}
}
}
答案 0 :(得分:6)
在第2部分中,genericanimal.genList
的类型为List<T>
= List<Animal>
。在第1部分中,列表的类型为List<? extends Animal>
。
问题在于List<? extends Animal>
表示“动物某些特定亚型的列表未知”。例如,您可以编写List<? extends Animal> list = new ArrayList<Cat>()
。并且你不应该能够将任何动物添加到猫的列表中。通过写List<? extends Animal>
,你说你想故意忘记哪种类型的动物被允许进入列表,尽管你知道列表中的任何内容都是一些动物类型。
答案 1 :(得分:0)
为什么在part1中,它在尝试将Animal对象添加到列表时引发了错误?
List<? extends Animal> totList = new ArrayList<Animal>();
totList.add(new Animal("Animal1",21)); // Error: Unresolved compilation problem:
因为编译器限制在使用上限有效通配符声明的列表上添加对象(?extends Animal)。编译器不确定列表是否输入动物,猫或狗。
很简单,只要使用Upper bounded Wildcard声明变量,就不允许在该变量中插入元素。
使用上限通配符的优点是:
为什么在part2中,在将Animal对象和Cat对象添加到列表时它没有抛出错误?
public List<T> genList = new ArrayList<T>();
genericanimal.genList.add(new Animal("Animal2",22)); // No Error, why?
genericanimal.genList.add(new Cat("Cat4",204));
因为这里的genList实际上是类型为Animal的格式,如下面的格式
List<Animal> genList = new ArrayList<Animal>();
现在就像普通的特定类型列表一样,它可以添加该类型的元素。
因此可以将Animal对象添加到List 允许添加Cat对象,因为它也只是一个Animal对象(Cat只是Animal的一个子类)
使用<T extends Animal>
的优势是: