Я думаю, что на самом деле этот только имеет смысл, когда параметр типа метода появляется как параметр типа параметризованного типа, который является частью сигнатуры метода.
(По крайней мере, я не смог бы быстро придумать пример, где он действительно имеет смысл в противном случае)
Это также тот случай, когда высвязаны с тем, где параметры типа метода используются в качестве параметров типа в классе AutoBean
.
Небольшое обновление:
На основе обсуждения ввопрос и другие ответы, суть этого вопроса, вероятно, была неверной интерпретацией способа использования параметров типа.Таким образом, этот вопрос может рассматриваться как дубликат Значениев объявлении Java-функции , но, надеюсь, кто-то сочтет этот ответ полезным, тем не менее.
В конце концов, причина использования шаблона <T, U extends T>
может быть видна в отношениях наследования параметризованных типов, которыев деталях может быть довольно сложным .В качестве примера, чтобы проиллюстрировать наиболее важный момент: A List<Integer>
является , а не подтипом List<Number>
.
Ниже приведен пример, показывающий, где это может изменить ситуацию.Он содержит «тривиальную» реализацию, которая всегда работает (и, насколько я могу судить, не имеет смысла).Но граница типа становится релевантной, когда параметры типа T
и U
также являются параметрами типа параметров метода и возвращаемого типа.С T extends U
вы можете вернуть тип, имеющий супертип в качестве параметра типа.В противном случае вы не смогли бы, как показано на примере, который // Does not work
:
import java.util.ArrayList;
import java.util.List;
public class SupertypeMethod {
public static void main(String[] args) {
Integer integer = null;
Number number = null;
List<Number> numberList = null;
List<Integer> integerList = null;
// Always works:
integer = fooTrivial(integer);
number = fooTrivial(number);
number = fooTrivial(integer);
numberList = withList(numberList);
//numberList = withList(integerList); // Does not work
// Both work:
numberList = withListAndBound(numberList);
numberList = withListAndBound(integerList);
}
public static <T, U extends T> T fooTrivial(U u) {
return u;
}
public static <T, U extends T> List<T> withListAndBound(List<U> u) {
List<T> result = new ArrayList<T>();
result.add(u.get(0));
return result;
}
public static <T> List<T> withList(List<T> u) {
List<T> result = new ArrayList<T>();
result.add(u.get(0));
return result;
}
}
(Конечно, это выглядит немного надуманным, но я думаю, что можно представить сценарии, в которых это действительно имеет смысл)