gpt4 book ai didi

java - Eclipse ECJ 接受此代码,javac 不接受 - 谁是对的?

转载 作者:搜寻专家 更新时间:2023-10-31 20:08:43 25 4
gpt4 key购买 nike

考虑以下 returnsNull函数并使用泛型类型调用它:

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 时接受它,但是 javac在 Java 8 中拒绝它:

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<?>>)

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

这不仅仅是理论上的思考:如果此代码被接受,它将解决我的 generics filtering problem .

谁是对的?

最佳答案

期间 applicability inference 欧洲法院推断<T>AtomicReference#RAW , 让我们签名 returnNull显示为

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

具体步骤是:

  • initial constraint :
    • ⟨Class<AtomicReference#RAW> → Class<? extends T#0>⟩
  • reduced to :
    • ⟨Class<AtomicReference#RAW> <: Class<? extends T#0>⟩
    • ⟨AtomicReference#RAW <= ? extends T#0⟩
    • ⟨AtomicReference#RAW <: T#0⟩
    • AtomicReference#RAW <: T#0
  • resolved to :
    • T#0 = AtomicReference#RAW

现在,传递 Class<AtomicReference#RAW> 类型的值没有问题了进入那个方法。

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

编辑: invocation type inference 期间情况看起来不同:通过将目标类型添加到混合中,我们最终(在 incorporation 期间)具有以下约束:

  • ⟨AtomicReference#RAW <: AtomicReference<?>⟩

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

我提交了 bug 528970以便欧洲法院进一步调查。

这有点讽刺意味,因为 javac has a long standing bug它错误地假设T#RAW <: T<X> .出于兼容性原因,ECJ 明确地将此错误复制到许多位置,但显然在一个特定的代码位置是相反的:javac 在 ECJ 检查兼容性的地方应用子类型。

编辑 2: 一年后,ECJ 中的错误似乎只能在 JLS 在 JDK-8054721 及其周围得到改进后才能修复。 .

关于java - Eclipse ECJ 接受此代码,javac 不接受 - 谁是对的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47662493/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com