Java中的参数化类型不匹配

时间:2015-02-25 08:50:55

标签: java class derived-class derived parameterized-types

我有三种类型,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>>

不应该基本上是X吗?如何使这个工作?

1 个答案:

答案 0 :(得分:2)

将声明与upper bounded wildcard

一起使用
doSomething(List<? extends X>)
即使List<S>List<T>

的子类型,

S也不是T的子类型

你可以用非常简单的方式思考这个问题。

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

输入通配符

因此,您可以使用通配符来执行此操作。 通配符参数化类型 List<? extends Animal>表示:“(一种类型)所有参数化类型的集合 - 通过调用泛型类型List<T>形成 - 使用类型参数< em>任何类型(通常称为“未知类型”) - 这是Animal(包括)的子类型。“

暗示这是一个潜在的无限集合,因为你可能有无数个Animal 的子类型(和List mumble的子类型混淆使问题混淆)

”参数

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

tldr:extends绑定意味着一个“in”变量(一个从中提取数据的变量,而不是一个用于输入数据的变量)

out ”参数

如果您希望将add(e) Dog添加到列表中,则需要通过声明doSomething(List<? super Dog>)将方法声明更改为“ out ”变量。现在你说“我可以将此列表视为保留任何类型为Dog ”的超类型:在调用站点,它可能是List<Dog>,{{1 }或List<Animal>。您现在可以List<Object> add(e)Dog子类型,例如Dog:所有内容都与任何可能的内容兼容传递的列表类型。您无法添加Mongrel,因为这没有意义:调用网站上的列表可能仍然是Cat,而不是List<Dog>

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

参考:Java教程&gt; Upper bounded wildcards