Рассмотрим следующий конструктор для класса Foo
(который для ясности не универсальный класс):
public <T> Foo(T obj) { }
Это допустимый синтаксис для конструкторов, как и в случае обычных универсальных методов .
Но какой смысл в этом синтаксисе? Обычно универсальные методы обеспечивают безопасность типов для своего возвращаемого типа и могут получить выгоду от вывода типа компилятором. Например:
Pair<String, Integer> stringInt = Pair.of("asfd", 1234);
Но вызов конструктора всегда возвращает экземпляр объявленного им класса, поэтому параметры его типа не влияют на тип возвращаемого значения. Приведенный выше конструктор можно просто заменить его erasure :
public Foo(Object obj) { }
Конечно, дженерики - это не только безопасность типов для возвращаемых типов. Конструктор может просто захотеть ограничить тип передаваемого аргумента (аргументов). Однако приведенные выше рассуждения все еще применимы к параметру ограниченного типа:
public <N extends Number> Foo(N number) { }
public Foo(Number number) { } //same thing
Даже параметры вложенного типа с границами обрабатываются с использованием подстановочных знаков:
public <N extends Number, L extends List<N>> Foo(L numList) { }
public Foo(List<? extends Number> numList) { } //same thing
Итак, каков законный вариант использования универсального конструктора?