因此,假设我们有一个 Java 应用程序,其中包含一个名为的抽象类SomeAbstractClass
以及该超类的至少 10 个子类。
在泛型中使用这个抽象超类有什么用,Collection<? extends SomeAbstractClass>
而不是仅仅使用Collection<SomeAbstractClass>
也许我错过了泛型中一些非常基本的东西。
这两种声明的区别:
Collection<? extends A> c1;
Collection<A> c2;
是否 c2 可以保存 A 或任何子类的实例,但 c1 可以保存 A(或 A)的某些未知但特定子类或任何未知类的子类的实例。
您不能将项目添加到 c2,因为编译器不知道它是什么类型,只有当您得到一个项目时,它才能被强制转换为 A。
此外,您不能将 c1 分配(即强制转换)给 c2 - c1 不是 c2 类型的子类。
泛型中的通配符用于集合类型,通常不用于存储的元素。
例如,想象一个采用参数的方法List<Number>
。
public void calculateSum(List<Number> numbers) {
for (Number n: numbers) {
// calculate Sum
}
}
现在,如果我们想通过传递来计算整数的总和,List<Integer>
如下所示。(注意这Integer
是 的子类Number
)
List<Integer> integers= new ArrayList<Integer>();
//Populate collection
calculateSum(integers); //Error
这将不起作用,因为即使Integers
is 的子类型不是Number
List<Integers>
的子List<Number>
类型。请注意,List<Number>
仍然可以存储Integer
,Float
等Double
。
因此,为了有一个通用的方法来计算任何类型的总和,Number
我们使用通配符如下
public void calculateSum(List<? extends Number> numbers) {
for (Number n: numbers) {
// calculate Sum
}
}
如果类型扩展,这将计算任何类型的数字的总和Number
以下在泛型中不正确,
Collection<? extends SomeAbstractClass>
^
|
|
Collection<SomeAbstractClass>
Collection<? extends SomeAbstractClass>
并且Collection<SomeAbstractClass>
是完全不同的类型并且不相关。
注意,
给定两个具体类型 A 和 B(例如 Number 和 Integer),MyClass 与 MyClass 没有关系,无论 A 和 B 是否相关。
例如,即使 Integer 是 Number 的List<Integer>
子类型,也不是的子类型。List<Number>
在您的情况下,它没有区别,因为类型是抽象的,但通常Collection<SomeClass>
可以包含SomeClass
它的所有子类,而Collection<? extends SomeClass>
不能包含SomeClass
但只能包含它的子类。
你可以自己试试。
List<Number> foo = new ArrayList<>();
foo.add(Integer.valueOf(0));
工作时
List<? extends Number> foo = new ArrayList<>();
foo.add(Integer.valueOf(0));
没有。它显示错误"The method add(capture#1-of ? extends Number) in the type List<capture#1-of ? extends Number> is not applicable for the arguments (Integer)"