I wonder why does this piece of code compile successfully?
Source code:
abstract class A<K extends Number>
{
public abstract <M> A<? super M> useMe(A<? super M> k);
}
Compiled successfully
How does it work and why does this compile? M is any type, so why it can be used?. Should it be: <M extends Number>
?
This will not compile:
abstract class A<K extends Number>
{
public abstract <M> A<? super M> useMe(A<M> k);
}
Error message:
type argument M is not within bounds of type variable K where M, K are type variables: M extends Object declared in method useMe(A) K extends Number declared in class A
What is the difference?
There are two parts to your question:
Part 1: What is the
<M>
?The presence of a generic parameter on a method makes it a "typed method", which means the method has a generic type that is determined by the caller, usually by inference. It may be bounded. If the class has a type too and the method is an instance method, the two types are unrelated.
Part 2:
The generic types must match exactly. The reason boils down to the fact that if
B
is a subtype ofA
,SomeClass<T extends B>
is not a subtype ofSomeClass<T extends A>
, more particularly,SomeClass<A>
is not a subtype ofSomeClass<? super A>
.