java - Java 中的参数化类型不匹配

标签 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>>

A本质上不应该是X吗?如何使其发挥作用?

最佳答案

使用带有 upper bounded wildcard 的声明

doSomething(List<? extends X>)

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

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

如果DogCatAnimal 的子类型你的方法是 doSomething(List<Animal> pets) ,然后在该方法中您可能 add一个Cat 。但如果pets呢?被传递为 List<Dog> ?您可能会出现过敏 react 。

输入通配符

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

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

in”参数

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

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

输出”参数

如果你想add(e)一个Dog在列表中,您需要通过声明 doSomething(List<? super Dog>) 将方法声明更改为“out”变量。现在你说“我可以将此列表视为包含 Dog 父类(super class)型的任何类型”:在调用站点,它可能是 List<Dog> , List<Animal>List<Object> 。您现在可以add(e)要么 Dog ,或 Dog子类型 ,就像 Mongrel :all 将与传递的任何可能类型的列表兼容。您无法添加Cat因为这没有任何意义:调用站点的列表仍然可能是 List<Dog> ,不是List<Animal> .

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

引用:Java 教程 > Upper bounded wildcards

关于java - Java 中的参数化类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28714715/

相关文章:

java - 如何使扩展另一个扩展类的类与通用集合一起使用?

c++ - 什么时候我们需要在纯C++程序中使用结构体?纯 C++ 程序中是否需要结构?

C++:直接使用派生类型的模板方法模式

动态添加属性和 setter 的 Pythonic 方式

java - 在java中,为什么Object类在成为一个类之后仍如此命名?

c++ - 具有模板化父类的派生类

c++ - 访问指定为私有(private)的基类的公共(public)静态成员

java - JPA 并发问题 "On release of batch it still contained JDBC statements"

java - ReadableByteChannel.read() 的行为

java - Android 图像上的文字