【问题标题】:How does Java handle ambiguous type inference for generics?Java 如何处理泛型的模糊类型推断?
【发布时间】:2018-02-17 22:56:16
【问题描述】:

在这段代码中,T 可以是 A、B、C 或 D,但 Eclipse 显示它是 D。

static class A { }
static class B extends A { }
static class C extends B { }
static class D extends C { }
static <T> void copy(List<? super T> dst, List<? extends T> src) {
    for (T t : src)
        dst.add(t);
}
public static void main(String[] args) {
    List<A> dst = new ArrayList<>();
    List<D> src = new ArrayList<>();
    copy(dst, src); // Eclipse shows T is D
}

对于如何进行类型推断以及为什么选择 D 是否有任何规则?

【问题讨论】:

  • Java 总是选择“最具体的”重载。显然,同样的逻辑也适用于此。
  • dst.addAll(src); 显示了什么?
  • 在 JLS 中找到了关于如何选择方法的相关部分,特别是关于“最具体的方法”的部分:docs.oracle.com/javase/specs/jls/se8/html/…(它是不太容易实现的方法之一) - 阅读 JLS 的部分内容,不过……)
  • (我会说这个问题肯定是另一个问题的重复,但我不确定该选择哪一个......(也许......(警告:蹩脚的双关语!).. .最具体的?...呵呵...)

标签: java generics type-inference generic-programming inferred-type


【解决方案1】:

有没有关于如何进行类型推断的规则

是的,entire 18th chapter of the Java Language Specification 专门讨论这个主题 :-)

为什么选择 D?

我认为以下规则对此负责:

如果边界集不包含形式为 G<... ...> = capture(G<...>) 对于所有 i (1 ≤ i ≤ n) 的边界,则 a为每个 αi 定义候选实例化 Ti:

  • 如果 αi 有一个或多个适当的下界 L1, ..., Lk,则 Ti = lub(L1, ..., Lk) (§4.10.4)。

  • 否则,如果绑定集包含 throws αi,并且 αi 的正确上界最多为 Exception、Throwable 和 Object,则 Ti = RuntimeException。

  • 否则,其中 αi 具有适当的上限 U1, ..., Uk, Ti = glb(U1, ..., Uk) (§5.1.10)。

边界 α1 = T1, ..., αn = Tn 与当前边界集合并。

如果结果不包含绑定的 false,则结果将成为新的绑定集,并且通过选择要实例化的新变量集(如果需要)继续解析,如上所述。

简单来说,在尝试类型参数的可能值时,编译器首先尝试下限,并在合适的情况下使用该下限。

在我们的例子中,约束集表示D extends T and D extends A,所以T 的下限是D,所以D 是第一个候选替换。

编译器通过假设T = D 来验证D 是否适合,这将约束集简化为D extends D and D extends A,这两者都是已知的。

因此,编译器使用D。

【讨论】:

  • 我对您在 JLS 的 absolute fustercluck 中分离出相关规则的速度印象深刻,并设法以简洁、可理解的方式进行解释 语言究竟如何应用于 OP 的示例。真正的典范。
  • @MikeStrobel - 我挑战你找到任何编程语言规范(对于非平凡的 PL)既严格和 外行人易于阅读。 (如果您认为 JLS 不好......请尝试理解原始的 Algol-68 规范。)
  • @Stephen-C 恐怕我必须拒绝你的挑战,因为我的小公寓只有这么多可以翻转的桌子。
  • 也许你应该多出去 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2018-04-01
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多