假设我有以下内容:
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/