Как правило, вам нужна только переменная типа, когда она используется более чем в одном месте в объявлениях класса / метода / поля. Когда вы объявляете один из методов (а не класса), единственными его местами являются параметры и возвращаемое значение этого метода.
Например, вы можете использовать его для нескольких параметров для обеспечения их типы соответствуют:
public static <T> void addToList(List<T> list, T element) {
list.add(element);
}
Это тривиальный пример, но вы можете видеть, что он мешает вам дать ему элемент, который не соответствует типичному типу списка:
List<Integer> list = new ArrayList<>();
addToList(list, 7);
//addToList(list, 0.7); // doesn't compile
//addToList(list, "a"); // doesn't compile
Вы также можете объявить параметр и тип возвращаемого значения одним и тем же типом:
public static <T> T nullCheck(T value, T defValue) {
return value != null ? value : defValue;
}
Так как этот метод возвращает один из двух T
объектов, которые он указан, мы можем с уверенностью сказать, что возвращенный объект также имеет тип T
.
Integer iN = null;
Integer i = nullCheck(iN, 7);
System.out.println(i); // "7"
Double dN = null;
Double d = nullCheck(dN, 0.7);
System.out.println(d); // "0.7"
Number n = nullCheck(i, d); // T = superclass of Integer and Double
System.out.println(n); // "7"
Что касается примера в вопросе, переменная типа используется только один раз, поэтому она эквивалентна использованию суперкласса. В этом случае вам следует избегать объявления переменной типа, это просто лишний беспорядок.
Также следует отметить, что другой ответ меняет пример использования List<T>
и List<Foo>
, но, как упоминалось в комментариях , суперкласс действительно List<? extends Foo>
, поэтому там не требуется никакая переменная типа.