Java 中的参数化类型不匹配

Parameterized Type Mismatch in Java

我有 A、B 和 X 三种类型

A<T extends Object> extends X
B extends Object

还有这个 api 电话

doSomething(List<X>)

我正在打这个电话

doSomething(ImmutableList.<A<B>>of(new A<B>(), new A<B>()))

但我收到错误消息:

List<X> cannot be applied to ImmutableList<A<B>>

A 本质上不应该是 X 吗?如何让它工作?

使用带有 upper bounded wildcard

的声明
doSomething(List<? extends X>)

List<S> 不是 List<T> 的子类型,即使 ST

的子类型

你可以用很简单的方式思考为什么会这样。

如果 DogCatAnimal 的子类型并且您的方法是 doSomething(List<Animal> pets),那么在方法内部您可能 add a Cat.但是,如果 pets 作为 List<Dog> 传递怎么办?您可能会出现过敏反应。

输入通配符

因此您可以使用通配符来做到这一点。 通配符参数化类型 List<? extends Animal> 表示:“(来自)所有参数化类型的集合 - 通过调用泛型类型 List<T> 形成 - 带有类型参数那是 任何类型(通常称为“未知类型”)——它是 Animal(含)的子类型。

暗示这是一个潜在的无限集合,因为您可能有无限数量的 Animal 子类型(以及 List mumble mumble 使问题复杂化的子类型 mumble) .

""参数

使用 List<? extends Animal> 表示“我同意最多将此列表中的所有内容视为 Animal”。简单来说,您不能再 add(e) 该列表中的任何内容,因为在方法内部您不知道调用站点上它是 List<Dog>List<Cat> 还是 List<Animal> .但是,您可以 get(index) 该列表参数中的任何项目并 feed() 它(假设 feed()Animal 上的方法)。它是一个“in”参数:它为方法提供数据。

tldr:extends 绑定意味着一个 "in" 变量(您从中提取数据的变量,而不是您将数据放入的变量)

"输出"参数

如果你想 add(e) 一个 Dog 进入列表你需要通过声明 doSomething(List<? super Dog>)。现在你说的是“我可以将这个列表视为包含 Dog 的超类型的任何类型”:在调用站点它可能是 List<Dog>List<Animal>List<Object>。您现在可以 add(e) DogDog 子类型 ,就像 Mongrel 一样:所有都将兼容任何可能传递的列表类型。您不能添加 Cat,因为那没有任何意义:调用站点的列表仍然可以是 List<Dog>,而不是 List<Animal>.

tldr:它是一个“out”参数:它 "stores" 来自方法内部的数据(因此可以将其提供回调用站点)。

参考文献:Java 教程 > Upper bounded wildcards