According to this entry in the Java Generics FAQ, there are some circumstances where a generic method has no equivalent non-generic method that uses wildcard types. According
Well, going by the spec, neither invocation is legal. But why does the first one type check while the second does not?
The difference is in how the methods are checked for applicability (see §15.12.2 and §15.12.2.2 in particular).
For simple, non-generic g
to be applicable, the argument Class
would need to be a subtype of Class extends Iterable>>
. That means ? extends Iterable>
needs to contain ArrayList
, written ArrayList <= ? extends Iterable>
. Rules 4 and 1 can be applied transitively, so that ArrayList
needs to be a subtype of Iterable>
.
Going by §4.10.2 any parameterization C<...>
is a (direct) subtype of the raw type C
. So ArrayList>
is a subtype of ArrayList
, but not the other way around. Transitively, ArrayList
is not a subtype of Iterable>
.
Thus g
is not applicable.
f
is generic, for simplicity let us assume the type argument ArrayList
is explicitly specified. To test f
for applicability, Class
needs to be a subtype of Class
. Since subtyping is reflexisve, that is true.
Also for f
to be applicable, the type argument needs to be within its bounds. It is not because, as we've shown above, ArrayList
is not a subtype of Iterable>
.
So why does it compile anyways?
It's a bug. Following a bug report and subsequent fix the JDT compiler explicitly rules out the first case (type argument containment). The second case is still happily ignored, because the JDT considers ArrayList
to be a subtype of Iterable>
(TypeBinding.isCompatibleWith(TypeBinding)
).
I don't know why javac behaves the same, but I assume for similar reasons. You will notice that javac does not issue an unchecked warning when assigning a raw ArrayList
to an Iterable>
either.