Единственная причина, которую я могу найти, чтобы иметь <T extends Object & Comparable<? super T>
, в отличии от T extends Comparable<? super T>
, для обеспечения обратной совместимости при родовой методе.
Согласно Ангелика Лангера Java Generics FAQ:
Иногда, нужно обратить внимание на то, что родовыми может изменить подпись некоторых методов в байт-код. Изменение подписи приведет к поломке существующего кода, который нельзя перекомпилировать, и полагается на двоичную совместимость старой и новой версии файла .class.
В этом случае Java Collections.max
используется для возврата Object
до 1,5, прихода дженериков. При генерации этот метод может быть объявлен без extends Object
, и он будет работать корректно изолированно.
public static <T extends Comparable<? super T>> T max(Collection <? extends T> coll)
Однако стирание этого метода, для целей байт-кода, этот метод имеет возвращающегося Comparable
вместо Object
, который представляет собой обратную несовместимость.
Для решения этой проблемы в качестве первой границы было вставлено extends Object
, так что стирание возвращаемого типа этого метода оставалось бы Object
.
Это разрешило проблему несовместимости в обратном направлении для генериков Java в 1.5.
Однако вопрос в учебнике говорится:
Написать шаблонный метод, чтобы найти максимальный элемент в диапазоне [begin, end)
списка.
Вы пишете свой собственный новый метод, поэтому нет обратной совместимости для поддержки. extends Object
в ответе на этот вопрос не нужен.
Кроме того
В байткодом (javap -c Algorithm.class
), все типы претерпевают типа стирания, даже локальную переменную maxElem
.
public static <T extends java.lang.Comparable<? super T>> T max(java.util.List<? extends T>, int, int);
Code:
0: aload_0
1: iload_1
2: invokeinterface #2, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
Метод get
возвратил Object
. Затем как он вызывает compareTo
в Comparable
?
7: astore_3
8: iinc 1, 1
11: iload_1
12: iload_2
13: if_icmpge 49
16: aload_3
17: checkcast #3 // class java/lang/Comparable
20: aload_0
21: iload_1
22: invokeinterface #2, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
27: invokeinterface #4, 2 // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
Компилятор вставил неявное приведение к Comparable
так, что метод compareTo
можно назвать. Он утверждал, что объекты в списке Comparable
из-за второй верхней границы, Comparable<? super T>
.
32: ifge 43
35: aload_0
36: iload_1
37: invokeinterface #2, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
42: astore_3
43: iinc 1, 1
46: goto 11
49: aload_3
50: areturn
}
Вопрос о том, что этот пост отмечен как дубликат, определенно связан, но это не совсем дубликат. Другой вопрос заключается в том, почему 'Collections.max' имеет' extends Object', но в связанном учебном вопросе/ответе от этого вопроса ответ (обратная совместимость) не применяется. – rgettman
@ rgettman Согласен. Первоначально я был связан с вопросом, что этот теперь является «дублированным» ** и ** на http://stackoverflow.com/questions/18411527/how-to-write-a-generic-method-to-find- метод-maximal-element-and-invoke-that-method, но по этой причине удалили первую ссылку: обратная совместимость здесь не применима. Ответ на другой вопрос объясняет вещь стирания типа довольно хорошо, поэтому закрытие все еще может быть оправдано. – Marco13