How does Java handle ambiguous type inference for generics?

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 made and why it chooses D?

+5
source share
1 answer

Is there any rule for how type inference is made

Yes, the whole 18th chapter of the Java language specification is dedicated to this topic :-)

and why does he choose D?

I think the following rule is responsible for this:

If the connected set does not contain an estimate of the form G <..., αi, ...> = capture (G <...>) for all i (1 ≤ i ≤ n), then a candidate copy Ti is defined for each αi:

  • If αi has one or more proper lower bounds, L1, ..., Lk, then Ti = lub (L1, ..., Lk) (§4.10.4).

  • Otherwise, if the associated set contains throws αi, and the proper upper bounds of αi are, at most, Exception, Throwable and Object, then Ti = RuntimeException.

  • Otherwise, where αi has its own upper bounds U1, ..., Uk, Ti = glb (U1, ..., Uk) (§ 5.1.1).

The estimates α1 = T1, ..., αn = Tn are included in the current connected set.

If the result does not contain a bound false, then the result becomes a new bound set, and the resolution continues, choosing a new set of variables to create the instance (if necessary), as described above.

In plain English, when you check for possible values ​​for a type parameter, the compiler first tries to use the lower bound and uses it if appropriate.

In our case, the set of constraints says that D extends T and D extends A , so the lower bound for T is D , so D is the first candidate replacement.

The compiler, which checks whether D is suitable, assuming that T = D , which simplifies this restriction set on D extends D and D extends A , both of which are known as true.

Therefore, the compiler uses D

+5
source

Source: https://habr.com/ru/post/1271654/


All Articles