Поскольку никто не дал удовлетворительного ответа, правильный ответ кажется «из-за недостатка языка Java».
polygenelubricants предоставили хороший обзор плохих вещей, происходящих с ковариантностью Java-массива, которая это ужасная особенность сама по себе. Рассмотрим следующий фрагмент кода:
String[] strings = new String[1];
Object[] objects = strings;
objects[0] = 0;
Этот явно неправильный код компилируется, не прибегая к какой-либо «супер» конструкции, поэтому ковариация массива не должна использоваться в качестве аргумента.
Теперь, здесь у меня есть вполне допустимый пример кода, требующего super
в параметре named type:
class Nullable<A> {
private A value;
// Does not compile!!
public <B super A> B withDefault(B defaultValue) {
return value == null ? defaultValue : value;
}
}
Потенциально поддерживая некоторое приятное использование:
Nullable<Integer> intOrNull = ...;
Integer i = intOrNull.withDefault(8);
Number n = intOrNull.withDefault(3.5);
Object o = intOrNull.withDefault("What's so bad about a String here?");
Последний фрагмент кода не компилируется, если я вообще удаляю B
, поэтому B
действительно необходим.
Обратите внимание, что функция, которую я пытаюсь реализовать, легко получить, если я инвертирую порядок объявлений параметров типа, изменив ограничение super
на extends
. Однако это возможно только в том случае, если я переписываю метод как статический:
// This one actually works and I use it.
public static <B, A extends B> B withDefault(Nullable<A> nullable, B defaultValue) { ... }
Дело в том, что это ограничение языка Java действительно ограничивает некоторые возможные полезные функции и может потребовать уродливые обходные пути. Интересно, что произойдет, если нам понадобится withDefault
, чтобы быть виртуальным.
Теперь, чтобы соотнести с тем, что говорят полигеномассы, мы используем B
здесь, чтобы не ограничивать тип объекта, переданного как defaultValue
( см. строку, используемую в примере), а скорее ограничить ожидания вызывающего абонента возвратом объекта. В качестве простого правила вы используете extends
с типами, которые вы требуете, и super
с типами, которые вы предоставляете.