java - 为什么我需要显式地进行通用调用?

标签 java generics

假设我有以下内容:

public <T extends Widget> List<T> first(T n) {
    return first(n.getClass());
}
public <T extends Widget> List<T> first(Class<T> n) {
    return new ArrayList<>();
}

编译器在第 3 行提示“incompatible types; required: java.util.List<T>; found: java.util.List<capture#1 of ? extends my.app.Widget>”。我不明白为什么。在我看来,类型 T 似乎是合理的除了子类型之外,在任何一种情况下都不会改变。

这可以通过显式转换来解决,但我不知道为什么需要它。

public <T extends Widget> List<T> first(T n) {
    return (List<T>)first(n.getClass());
}
public <T extends Widget> List<T> first(Class<T> n) {
    return new ArrayList<>();
}

这可能是编译器错误吗?

请注意,我使用的是 JDK 1.7.0_15:

java version "1.7.0_15"
Java(TM) SE Runtime Environment (build 1.7.0_15-b03)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

最佳答案

正是出于您所说的原因,类型参数实际上可能是您传入的对象的实际运行时类型的父类(super class)型! T#getClass()不返回 Class<T> , 它返回 Class<? extends T>

Number number = Integer.valueOf(1);
List<Number> list = first(number);

当您调用 n.getClass() 时在运行时将返回 Integer.class , 不是 Number.class ,但您正试图将结果分配给 List<Number> !编译器无法知道真正的运行时类型是什么,它最多只知道 List<? extends Number>。回来。强制您进行类型转换是其表达“我无法保证此操作的安全性,您保证它是正确的”的方式。

任何时候编译器都不可能确认一个操作是类型安全的,它会强制你进行强制转换,从而引发“未检查”警告,这样它就完成了让你知道问题的工作。

关于java - 为什么我需要显式地进行通用调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15265138/

相关文章:

java - 将通用枚举从 Java 转换为 Kotlin

scala - 为什么 trait 方法需要 asInstanceOf 而类方法不需要

java - 如何使用 SAX 解析器在 XML 中添加元素?

Java诗歌回文检查器: Iterate through array matching elements in order

java - 如何根据 JComboBox 选择更改 JTextField

java - 一个intellij模块有多个SDK

java - 调用其参数受交集类型限制的方法

java - GWT 简单网络表单提交 - 重定向到新页面

Java 泛型 - 确保实现静态方法

java - 帮助 Java 泛型 : Cannot use "Object" as argument for "? extends Object"