super
для привязки параметра именованного типа (например, <S super T>
) в отличие от подстановочного знака (например, <? super T>
) - это ILLEGAL просто потому, что даже если это разрешено, оно не будет делать то, что Вы надеялись, что это сработает, потому что Object
является максимальным super
из всех ссылочных типов, а все это Object
, , в действительности нет границы .
В вашем конкретном примере, поскольку любой массив ссылочного типа представляет собой Object[]
(по ковариации Java-массива), поэтому его можно использовать в качестве аргумента для <S super T> S[] toArray(S[] a)
(если такая граница допустима ) во время компиляции, и это не помешает ArrayStoreException
во время выполнения.
Вы пытаетесь предложить следующее:
List<Integer> integerList;
и с учетом этого гипотетического super
, связанного с toArray
:
<S super T> S[] toArray(S[] a) // hypothetical! currently illegal in Java
компилятор должен разрешать компилировать только следующее:
integerList.toArray(new Integer[0]) // works fine!
integerList.toArray(new Number[0]) // works fine!
integerList.toArray(new Object[0]) // works fine!
и никаких других аргументов типа массива (поскольку Integer
имеет только эти 3 типа как super
). То есть вы пытаетесь предотвратить компиляцию:
integerList.toArray(new String[0]) // trying to prevent this from compiling
потому что, по вашему аргументу, String
не является super
из Integer
. Однако , Object
- это super
из Integer
, а String[]
- это Object[]
, поэтому компилятор все еще позволит скомпилировать приведенный выше код, даже если гипотетически вы можете сделать <S super T>
!
Таким образом, следующее будет по-прежнему компилировать (как и сейчас), и ArrayStoreException
во время выполнения не может быть предотвращено любой проверкой во время компиляции с использованием границ универсального типа:
integerList.toArray(new String[0]) // compiles fine!
// throws ArrayStoreException at run-time
Дженерики и массивы не смешиваются, и это одно из многих мест, где оно отображается.
Пример без массива
Опять, скажем, у вас есть это объявление общего метода:
<T super Integer> void add(T number) // hypothetical! currently illegal in Java
И у вас есть следующие объявления переменных:
Integer anInteger
Number aNumber
Object anObject
String aString
Ваше намерение с <T super Integer>
(если это законно) состоит в том, чтобы оно разрешало add(anInteger)
, add(aNumber)
и, конечно, add(anObject)
, но НЕ add(aString)
. Ну, String
- это Object
, поэтому add(aString)
все равно будет компилироваться.
См. Также
Похожие вопросы
О правилах набора шаблонов:
При использовании super
и extends
: