在原始类类型上忽略的显式方法类型参数;编译器错误? [英] Explicit method type parameter ignored on a raw class type; compiler bug?

查看:125
本文介绍了在原始类类型上忽略的显式方法类型参数;编译器错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用显式类型参数调用泛型方法时遇到编译器错误,好像未考虑显式类型参数一样.最小的例子:

I am getting a compiler error calling a generic method with explicit type parameters, as if the explicit type parameter had not been taken into account. Minimal example:

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 类型参数,而是提供了方法类型参数.根据我对JLS的理解,这应该是合法的,但这给了我这个错误:

ThingProducer is a raw type since the class has a type parameter, but in calling getThing we are not referencing the class type parameter, but instead providing the method type parameter. Per my understanding of the JLS, this should be legal, but it gives me this error:

incompatible types: Object cannot be converted to ThingA

如果我消失

  • ThingProducer
  • 中删除<S>
  • 或将getThing设为静态
  • 声明thingProducer ThingProducer<?>而不是原始类型ThingProducer
  • remove the <S> from ThingProducer
  • or make getThing static
  • declare thingProducer ThingProducer<?> instead of the raw type ThingProducer

这是编译器错误吗?如果不是,那么JLS中的哪个规则定义了此行为?

Is this a compiler bug? If not, what rule in the JLS defines this behavior?

推荐答案

未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)的类型为原始类型.对应于在对应于C的通用声明中删除其类型.

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.

在您的示例中,getThing()是未继承的原始类型C的实例方法... [在这种情况下为ThingProducer]".根据JLS,其类型为与在通用声明中删除其类型相对应的原始类型".在getThing()的通用声明中,其类型T是无界的,这意味着其擦除为java.lang.Object.

In your example, getThing() is an "instance method ... of a raw type C [in this case, ThingProducer] which is not inherited". According to the JLS, its type is "the raw type that corresponds to the erasure of its type in the generic declaration". In the generic declaration of getThing() its type T is unbounded, which means its erasure is java.lang.Object.

请注意,规范没有getThing()的类型是通过擦除其所属的原始类型(即ThingProducer)而构造的类型-实际上是getThing()本身的擦除,这意味着两个类型参数(TS)都将被擦除.

Note that the spec does not say that getThing()'s type is the type constructed by erasing the raw type of which it is a member (that is, ThingProducer) -- it is actually the erasure of getThing() itself, which means that both type parameters (T and S) are erased.

[另外:在我的原始答案中,我引用了规范的另一句话:将类型参数传递给未从其超类继承的原始类型的非静态类型成员时,这是编译时错误超级接口".我最初读这句话的原因是,需要编译器才能针对您的上述语法发出编译时错误,因为我得出的结论是您试图将类型参数传递给非静态类型成员"原始类型".但是我改变了主意:我相信最后一句话是指非静态的 type 成员(即嵌套类型),而不仅仅是一个非静态的 type 成员.静态通用成员.]

[Aside: In my original answer, I quoted another sentence of the spec: "It is a compile-time error to pass type arguments to a non-static type member of a raw type that is not inherited from its superclasses or superinterfaces." My original reading of that sentence was that the compiler is required to emit a compile-time error for your syntax above, since I concluded that you were attempting to "pass type arguments to a non-static type member of a raw type". But I've changed my mind: I believe that last sentence is referring to a non-static type member (that is, a nested type), not merely a non-static generic member.]

当然,如果不引用规范中的以下内容,则对4.8节的讨论是不完整的:

Of course, no discussion of section 4.8 is complete without quoting this bit from the spec:

仅允许出于对遗留代码兼容性的考虑而使用原始类型.强烈建议不要在将泛型引入Java编程语言后在编写的代码中使用原始类型.将来的Java编程语言版本可能会禁止使用原始类型.

The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of generics into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.

这篇关于在原始类类型上忽略的显式方法类型参数;编译器错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆