Интересно, почему этот фрагмент кода успешно компилируется?
Исходный код:
abstract class A<K extends Number>
{
public abstract <M> A<? super M> useMe(A<? super M> k);
}
Компилировано успешно
Как это работает и почему это компилируется? M — это любой тип, так почему же его можно использовать? Должно быть: <M extends Number>
? Это не будет компилироваться:
abstract class A<K extends Number>
{
public abstract <M> A<? super M> useMe(A<M> k);
}
Сообщение об ошибке:
аргумент типа M не находится в границах переменной типа K, где M, K являются переменными типа: M extends Объект, объявленный в методе useMe(A) K extends Число, объявленное в классе A
В чем разница?
<M>
на<M extends Number>
в более поздних версиях также позволяет скомпилировать его. - person Guvante   schedule 24.12.2013<? super M>
всегда включаетobject
, который в любом случае не может удовлетворить требование. - person Guvante   schedule 24.12.2013A<M> k
: граница типовM
на самом деле строгоObject
во время компиляции, но поскольку ваш классA<K extends Number>
объявленA
, его можно параметризовать только с типом, с которым верхняя границаNumber
. Однако первый компилируется, потому что использование? super M
как минимум убеждает компилятор в том, что тип может иметь привязку, отличную отObject
, и может быть обнаружен во время выполнения. - person Sage   schedule 24.12.2013