我以为我用super
找出了仿制药。但我一定是完全错了:
通过这个简单的例子:
class Animal{}
class Dog extends Animal{}
这段代码工作正常,因为我们正在传递一个超类Dog:
static void addThis(ArrayList<? super Dog> a) {
a.add(new Dog());
}
...
ArrayList<Animal> dogs=new ArrayList();
addThis(dogs);
然而,我不明白的是我认为这是同一件事:
ArrayList<? super Dog> dogs2=new ArrayList();
dogs2.add(new Animal());
但它无法编译。这两者有什么区别?
顺便说一下,我想偷偷回答另一个问题。
之间有什么区别吗?// This...
ArrayList<Animal> dogs=new ArrayList();
// ... and this?
ArrayList<Animal> dogs=new ArrayList<Animal>();
给定类型擦除在编译时删除它我认为它与编译器检查引用类型是一回事。这是对的吗?
答案 0 :(得分:4)
它根本不是一回事。在一个案例中,您要添加Dog
,而在另一种情况下,您需要添加Animal
。
在这两种情况下,只有知道允许Dog
,所以第二种情况失败。
要回答第二个问题,是的区别,您应该始终使用第二个版本。 (但在Java 7+中,您可以通过编写new ArrayList<>()
请求编译器为您推断泛型类型。)
答案 1 :(得分:0)
狗是动物,所以你可以将ArrayList<? extends Dog>
施放到ArrayList<Animal>
,但你不能走另一条路,因为动物不一定是狗。
例如:
public class Cat extends Animal{}
因为这没有意义:
ArrayList<Dog> dogList = new ArrayList<Dog>();
dogList.add(new Cat());
您无法将动物添加到狗列表中,因为动物可能是猫。
这是Java类型安全的一个例子。
答案 2 :(得分:0)
简单地说,List<? super Dog>
是super
(父)作为Dog
的对象列表,而不是super
Dog
的对象列表}