Я понимаю, что вы не можете связать параметр типа универсального Java-кода с нижней границей (то есть, используя ключевое слово super
). Я читал, что Angelika Langer Generics FAQ должен сказать по этому вопросу . Они говорят, что это сводится к тому, что нижняя граница бесполезна («не имеет никакого смысла»).
Я не уверен. Я могу представить себе их использование, чтобы помочь вам быть более гибким в обращении к методам библиотеки, которые дают типизированный результат. Представьте себе метод, который создал список массивов указанного пользователем размера и заполнил его пустой строкой. Простая декларация будет
public static ArrayList<String> createArrayListFullOfEmptyStrings(int i);
Но это неоправданно ограничивает ваших клиентов. Почему они не могут вызвать ваш метод так:
//should compile
List<Object> l1 = createArrayListFullOfEmptyStrings(5);
List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
List<String> l3 = createArrayListFullOfEmptyStrings(5);
//shouldn't compile
List<Integer> l4 = createArrayListFullOfEmptyStrings(5);
В этот момент у меня возникнет соблазн попробовать следующее определение:
public static <T super String> List<T> createArrayListFullOfEmptyStrings(int size) {
List<T> list = new ArrayList<T>(size);
for(int i = 0; i < size; i++) {
list.add("");
}
return list;
}
Но он не скомпилируется; ключевое слово super
в этом контексте недопустимо.
Является ли мой пример выше плохим примером (игнорируя то, что я говорю ниже)? Почему здесь не полезна нижняя граница? И если это будет полезно, какова реальная причина того, что это не разрешено в Java?
приписка
Я знаю, что лучшая организация может быть примерно такой:
public static void populateListWithEmptyStrings(List<? super String> list, int size);
List<CharSequence> list = new ArrayList<CharSequence>();
populateListWithEmptyStrings(list, 5);
Можем ли мы для целей этого вопроса сделать вид, что из-за требования нам нужно выполнить обе операции в одном вызове метода?
Редактировать
@ Том Дж (обоснованно) спрашивает, какую выгоду, если бы List<CharSequence>
имел бы, чем List<String>
. С одной стороны, никто не сказал, что возвращаемый список является неизменным, поэтому вот одно из преимуществ:
List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
l2.add(new StringBuilder("foo").append("bar"));