Eclipse ECJ 接受此代码,javac 不接受 - 谁是对的? [英] Eclipse ECJ accepts this code, javac doesn't - who is right?

查看:23
本文介绍了Eclipse ECJ 接受此代码,javac 不接受 - 谁是对的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下 returnsNull 函数和对它的泛型调用:

Consider the following returnsNull function and a call to it with a generic type:

public static <T> List<T> returnNull(Class<? extends T> clazz) {
    return null;
}

public static void main( String[] args )
{
    List<AtomicReference<?>> l = returnNull(AtomicReference.class);
}

Eclipse 编译器在设置为 Java 8 时接受它,但 Java 8 中的 javac 拒绝它:

The Eclipse compiler, when set to Java 8, accepts it, but javac in Java 8 rejects it with:

incompatible types: cannot infer type-variable(s) T
    (argument mismatch; java.lang.Class<java.util.concurrent.atomic.AtomicReference> cannot be converted to java.lang.Class<? extends java.util.concurrent.atomic.AtomicReference<?>>)

潜在的区别似乎是给定两个参数化类型 P1P2,Eclipse 允许从使用原始参数化的外部类型进行转换内部类型:P1<P2> 到外部类型参数化,内部类型的下限带有无界通配符,如 P1.javac 没有.

The underlying difference seems to be that given a two parameterized types P1<T> and P2<T>, Eclipse allows conversion from the outer type parameterized with the raw inner type: P1<P2> to the outer type parameterized with a lower bound of the of the inner-type with an unbounded wildcard like P1<? extends P2<?>>. javac doesn't.

这不仅仅是理论上的思考:如果此代码被接受,它将解决我的泛型过滤问题.

This isn't just a theoretical musing: if this code was accepted it would solve my generics filtering problem.

谁是对的?

推荐答案

适用性推断 ECJ 将 推断为 AtomicReference#RAW,让我们 returnNull 的签名显示为

During applicability inference ECJ infers <T> to AtomicReference#RAW, which let's the signature of returnNull appear as

List<AtomicReference#RAW> returnNull(Class<? extends AtomicReference#RAW>)

具体步骤是:

  • 初始约束:
    • ⟨Class→ 类
    • ⟨Class<:类<?扩展 T#0>⟩
    • ⟨AtomicReference#RAW <= ?扩展 T#0⟩
    • ⟨AtomicReference#RAW <: T#0⟩
    • AtomicReference#RAW <: T#0
    • T#0 = AtomicReference#RAW

    现在,将 Class 类型的值传递到该方法中没有问题.

    Now, there's no problem passing a value of type Class<AtomicReference#RAW> into that method.

    (后缀#RAW 是原始类型的实现特定表示,为了清楚起见,在此复制).

    调用类型推断:通过将目标类型添加到混合中,我们最终(在 incorporation) 具有以下约束:

    • ⟨AtomicReference#RAW <: AtomicReference

    此约束应减少为 FALSE,但 ecj 减少为 TRUE.由此看来,拒绝该计划似乎是正确的答案.

    This constraint should reduce to FALSE, but ecj reduces to TRUE. From this, rejecting the program seems to be the correct answer.

    我已向欧洲法院提交了错误 528970 以供进一步调查.

    I filed bug 528970 for further investigation in ECJ.

    这有点讽刺,因为javac 有一个长期存在的错误 从而错误地假设 T#RAW <: T.出于兼容性原因,ECJ 明确地将此错误复制到了许多位置,但显然在一个特定的代码位置,情况正好相反:javac 在 ECJ 检查兼容性的地方应用子类型.

    There is some irony in this, because javac has a long standing bug whereby it wrongly assumes T#RAW <: T<X>. For compatibility reasons, ECJ explicitly copied this bug into many locations, but apparently in one particular code location it's the opposite: javac applies subtyping where ECJ checks for compatibility.

    编辑 2: 一年后,似乎只有在 JLS 在 JDK-8054721.

    EDIT 2: One year later it seems that the bug in ECJ can only be fixed after JLS has been improved in and around JDK-8054721.

    这篇关于Eclipse ECJ 接受此代码,javac 不接受 - 谁是对的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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