我知道泛型是不变的:对于任何两个不同的类型 Type1 和 Type2, List< Type1> 既不是 List< 的子类型也不是其父类(super class)型 类型2>
所以
List<someObject> nums = new ArrayList<someObject>(); // this is correct
List<Object> nums = new ArrayList<subObject>(); // this is not correct
但是
List<Number> nums = new ArrayList<Number>();
List<? super Number> sink = nums; ????(line 2)
假设通配符是对象,那么第 2 行将是
List<Object> sink = List<Number> nums
这里似乎不适用不变规则
谁能向我解释一下为什么第 2 行编译时没有错误?
非常感谢
最佳答案
如果我没记错的话,您希望了解以下有效代码的解释:
List<Number> nums = new ArrayList<Number>();
List<? super Number> sink = nums;
不变性是类的属性,其类型参数如何影响其子类型。
泛型是不变的,但通配符的存在可以帮助我们进行子类型化。它们不是很有用,因为它们不代表任何类型,但代表了一个很好的技巧。以下是有效的
List<Animal> <: List<?>
List<?> <: List
更好的例子:
List<? super Animal> d1= new ArrayList<Animal>();
d1.add(new Animal());
d1.add(new Dog());
上面的方法有效,因为 d1
类型为List<? super Animal>
。你可以想象add
函数的行为如下:
boolean add(? super Animal e);
所以到add
方法,您可以传递 ? super Animal
的子类型的任何变量。并且
Animal <: ? super Animal
Dog <: ? super Animal
所以添加狗或动物是可行的。所以d1
充当一个列表,可以采用 Animal
类型的任何参数或子类型(如果有)。
同样的,你也可以有下面的。但从技术上讲,您无法向此列表添加任何内容。如果java中存在某种类型,它是每种类型的子类型,那么您可以正确地向其中添加该类型的元素。没有别的了。
ArrayList<? extends Animal> d1 = new ArrayList<Animal>();
查看此答案以了解更多信息 info .
关于java - java泛型中的通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28530644/