Java如何处理泛型的模糊类型推断?

时间:2017-09-09 00:54:38

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

在此代码中,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?

的规则

1 个答案:

答案 0 :(得分:5)

  

是否有关于类型推断如何完成的规则​​

是的,entire 18th chapter of the Java Language Specification致力于此主题: - )

  

为什么选择D?

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

  

如果绑定集合不包含形式G&lt; ...,αi,...&gt;的边界。 =对于所有i(1≤i≤n)捕获(G&lt; ...&gt;),然后为每个αi定义候选实例化Ti:

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

  •   
  • 否则,如果绑定集包含抛出α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是第一个候选替换。

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

因此,编译器使用D