Are you sure? My test is that the 1st m(cInteger, cInteger)
fails, and the second m(cSomething, cSomething)
is fine. In addition, raw m(x,x)
does not compile.
(1) m(cInteger,cInteger)
does not work
Both m () correspond to arguments; for m2, the output prints S=U=Class<Integer>
.
Now the question is, is m1 more specific than m2? Following the procedure described in 15.12.2.5, this is so. If so, then there is no ambiguity; m1 should be chosen as the most specific method, and the call should be compiled.
However, this violates the informal requirement specified by the specification: if m1 is more specific than m2, any call processed by m1 can be transferred to m2 without a compilation type error. For example, m1 can take arguments (Class<Integer>,Class<String>)
that m2 cannot (due to a lower (than ideal) output procedure).
Javak obviously adheres to an informal concept; this is probably because the formal specification has a mistake β it should have included the capture transformation (explained later) in the definition of a more specific relationship; then m1 is at most m2, so the call to m(cInteger,cInteger)
ambiguous.
If the other compiler strictly adheres to the formal specification, it is not its fault to inherit the spec error.
(2) m(x, x)
does not work
for the same reason as (1); both methods are consistent with each other, but no more specific than the others.
m1 corresponds to the conversion of the method call, which allows you to uncheck the conversion from raw Class
to Class<?>
. m2 after output S=U=Class
(3) m(cSomething, cSomething)
compiles
This is because m1 is the only one applicable, therefore there is no ambiguity.
m2 is not applicable, let's see why.
Firstly, the argument types are not exact (Class<?>,Class<?>)
- capture conversion is applied first. (Again, the specification is very obscure (see Chapter 15), but I am very sure that this is well understood in this case, the type of any expression is applied with capture conversion)
Thus, the argument types (Class<X1>,Class<X2>)
, with two new type variables. There is another disgust, a more accurate conversion would be (Class<X1>,Class<X1>)
, unfortunately, the capture transformation is applied twice, independently, exposing two different types.
m1 easily matches argument types. But m2 does not match, due to the type inference procedure of a less perfect type. First, the procedure gives S=Class<X1>, U=Class<X2>
, after which the constraints of variables of the type where U extends S
fails are checked.
(4) U bound removal
Now (1), (2), (3) all are compiled. Since without U extends S
, the output goes through.
For (1) and (2), m1 is now more specific than m2, no longer ambiguous.
For (3) now corresponds to m2; but then obscured by a more specific m1