Ответ 1
Одним из преимуществ ?
является то, что он запрещает добавление элементов в Collection
В Java класс Collections содержит следующий метод:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)
Его подпись хорошо известна своим расширенным использованием дженериков, настолько, что упоминается в Java в двух словах и в официальном Учебном пособии Sun Generics.
Однако я не смог найти убедительного ответа на следующий вопрос:
Почему формальный параметр типа Collection<? extends T>
, скорее
чем Collection<T>
? Какая дополнительная польза?
Одним из преимуществ ?
является то, что он запрещает добавление элементов в Collection
Вывод типа - это сложная тема, которую я признаю, что я об этом не знаю. Однако рассмотрите этот пример:
public class ScratchPad {
private static class A implements Comparable<A> {
public int compareTo(A o) { return 0; }
}
private static class B extends A {}
private static class C extends B {}
public static void main(String[] args)
{
Collection<C> coll = null;
B b = Scratchpad.<B>min(coll);
}
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c) {
return null;
}
//public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
// return null;
//}
}
Учтите, что первая подпись min() позволяет компиляции вызова, а вторая - нет. Это не очень практичный пример, так как нужно спросить, почему я должен явно вводить метод в <B>
, но, возможно, существует неявный вывод, где B
будет выведенным типом.
Я думаю, что на самом деле это не дает вам ничего больше для этого метода, однако его хорошая привычка вступать, когда T является частью класса, а не только статическим методом.
Они включают его здесь, чтобы он мог стать новым соглашением, в котором каждый родословный должен быть расширен на?
Класс T должен следовать за PECS: Что такое PECS (продюсер продлевает потребительский супер)?
Но статическому методу не нужно (по крайней мере, параметры, всегда возвращаемое значение)
Это поддержка устаревшей сигнатуры метода в Java 1.4 (и раньше).
До появления Java 5 сигнатура для этих методов была
public static Object min ( Collection c );
С несколькими ограничениями правила стирания делают первую границу необработанным типом метода, поэтому без Object &
подпись будет
public static Comparable min ( Collection c );
и устаревший код сломается.
Это взято из книги генералов и коллекций O'Reilly Java, глава 3.6
Основываясь на комментариях, которые я поставил на ответ Марка, если у вас есть что-то вроде
class Play {
class A implements Comparable<A> {
@Override
public int compareTo(A o) {
return 0;
}
}
class B extends A {
}
class C extends A {
}
public static <T extends Object & Comparable<? super T>> T min(
Collection<? extends T> c) {
Iterator<? extends T> i = c.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
public static List<? extends A> getMixedList() {
Play p = new Play();
ArrayList<A> c = new ArrayList<A>();
c.add(p.new C());
c.add(p.new B());
return c;
}
public static void main(String[] args) {
ArrayList<A> c = new ArrayList<A>();
Collection<? extends A> coll = getMixedList();
A a = Play.min(coll);
}
}
Ясно, что min возвращает объект типа A (фактическая подпись <A> A Play.min(Collection<? extends A> c)
). Если вы оставите min(Collection<T>)
без части расширения, то Play.min(coll)
будет иметь следующую подпись <? extends A> ? extends A Play.min(Collection<? extends A> c)
, которая не так понятна.