java - java泛型中的通配符

标签 java generics

我知道泛型是不变的:对于任何两个不同的类型 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/

相关文章:

java - 将 JComponents 与 JPanel 的左侧和右侧对齐

JavaFX:如何覆盖自定义对话框中的按钮操作

java - 向 Android 电报源代码添加新语言

java - 以 CamelCase 风格化的单词的正确常量命名约定是什么?

c# - 动态设置类型或调用泛型方法的结果?

java - Camel::Generic List<Enum> 转换器

node.js - 如何在 TypeScript 中通过索引访问通用对象的属性?

java - 设置构造函数参数时无法解析对 bean 'entityManagerFactory' 的引用

c# - 多个约束泛型类型的字典和接口(interface)

java - 为什么不能将具有其他类型的实例分配给参数化变量?