In this code, T can be A, B, C, or D, but Eclipse shows that it is 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
}
Is there any rule for how type inference is done and why it selects D?
Yes, the entire 18th chapter of the Java Language Specification is dedicated to this topic :-)
I think the following rule is responsible for that:
In plain english, when trying out possible values for a type parameter, the compiler first tries the lower bound, and uses that one if it fits.
In our case, the constraint set says that
D extends T and D extends A
, so the lower bound forT
isD
, soD
is the first candidate substitution.The compiler than verifies whether
D
fits by assuming thatT = D
, which simplifies that constraint set toD extends D and D extends A
, both of which are known to be true.Therefore, the compiler uses
D
.