В Java класс Наборов содержит следующий метод:
public static > T min(Collection extends T> c)
Его подпись известна за его усовершенствованное использование дженериков, так что это упоминается в Java, вкратце заказывают и в официальном Учебном руководстве по Дженерикам Sun.
Однако я не мог найти убедительный ответ на следующий вопрос:
Почему формальный параметр типа Collection extends 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
будет предполагаемый тип.
Я думаю, что на самом деле это не дает вам ничего большего для этого метода, однако это хорошая привычка, которую нужно выработать, когда T является частью класса, а не просто статическим методом.
Они включают его сюда, чтобы он стал новой конвенцией, по которой каждый generic должен быть расширен на ?
Класс T должен следовать PECS: Что такое PECS (Producer Extends Consumer Super)?
Но статическому методу это не нужно (по крайней мере, параметрам, возвращаемое значение должно быть всегда)
Основываясь на комментариях, которые я добавил к ответу Марка, если у вас есть что-то вроде
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 Play.min (Коллекция Extends A> c)
). Если вы оставите min (Collection
без расширяемой части, тогда Play.min (coll)
будет иметь следующую подпись расширяет A>? расширяет A Play.min (Collection extends A> c)
, что не так ясно.
Это необходимо для поддержки устаревшей сигнатуры метода в Java 1.4 (и ранее).
До Java 5 подпись для этих методов была
public static Object min ( Collection c );
С несколькими границами правила стирания делают первую привязку необработанным типом метода, поэтому без Object &
подпись будет
public static Comparable min ( Collection c );
и устаревший код сломается.
Это взято из книги О'Рейли по обобщениям и коллекциям Java, глава 3.6