我在调用具有显式类型参数的泛型方法时收到编译器错误,就好像未考虑显式类型参数一样。最小的例子:
class CastExample {
static class ThingProducer<S> {
public <T> T getThing() { return null; }
}
static class ThingA {}
public static void main(String... args) {
ThingProducer thingProducer = new ThingProducer();
ThingA thingA = thingProducer.<ThingA>getThing(); // compile error here
}
}
ThingProducer
是一个原始类型,因为该类有一个类型参数,但在调用时getThing
我们没有引用class类型参数,而是提供method类型参数。根据我对 JLS 的理解,这应该是合法的,但它给了我这个错误:
incompatible types: Object cannot be converted to ThingA
如果我这样做,错误就会消失
- 去除
<S>
from ThingProducer
- or make
getThing
static
- declare
thingProducer ThingProducer<?>
而不是原始类型ThingProducer
这是编译器错误吗?如果不是,JLS 中的什么规则定义了这种行为?
Java 语言规范第 4.8 节回答你的问题:
未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是对应于的原始类型删除对应于 C 的泛型声明中的类型。
在你的例子中,getThing()
是原始类型 C 的“实例方法......”[在这种情况下,ThingProducer
] 不是继承的”。根据 JLS,它的类型是“对应于泛型声明中其类型擦除的原始类型”。在泛型声明中getThing()
它的类型T
是无界的,这意味着它的擦除是java.lang.Object
.
请注意,规范确实not比如说getThing()
的类型是通过擦除它所属的原始类型而构造的类型(即ThingProducer
)——实际上是擦除getThing()
本身,这意味着两个类型参数 (T
and S
)被删除。
[旁白:在我原来的回答中,我引用了规范的另一句话:“将类型参数传递给不是从其超类或超接口继承的原始类型的非静态类型成员是一个编译时错误。”我最初读到这句话是编译器是required为上面的语法发出编译时错误,因为我得出的结论是您试图“将类型参数传递给原始类型的非静态类型成员”。但我改变了主意:我相信最后一句指的是非静态type成员(即嵌套类型),而不仅仅是非静态泛型成员。]
当然,如果不引用规范中的这一点,第 4.8 节的讨论就不完整:
仅允许使用原始类型作为对遗留代码兼容性的让步。强烈建议不要在 Java 编程语言中引入泛型之后编写的代码中使用原始类型。 Java 编程语言的未来版本可能会禁止使用原始类型。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)