В чем разница между ограниченным шаблоном и параметрами типа?
Есть ли разница между
Collection getThatCollection(Class type)
а также
Collection getThatCollection(Class)
Они выставляют разные интерфейсы и заключают контракт на этот метод.
Первое объявление должно возвращать коллекцию, тип элементов которой совпадает с classом аргументов. Компилятор указывает тип N
(если не указан). Таким образом, следующие два утверждения действительны при использовании первого объявления:
Collection c1 = getThatCollection(Integer.class); Collection c2 = getThatCollection(Double.class);
Второе объявление не объявляет связь между возвращаемым аргументом типа коллекции classу аргументов. Компилятор предполагает, что они не связаны друг с другом, поэтому клиенту придется использовать возвращаемый тип как Collection extends Number>
Collection extends Number>
, независимо от аргумента:
// Invalid statements Collection c1 = getThatCollection(Integer.class); // invalid Collection c2 = getThatCollection(Double.class); // invalid Collection cN = getThatCollection(Number.class); // invalid // Valid statements Collection extends Number> c3 = getThatCollection(Integer.class); // valid Collection extends Number> c4 = getThatCollection(Double.class); // valid Collection extends Number> cNC = getThatCollection(Number.class); // valid
Рекомендация
Если действительно существует связь между типом между аргументом возвращаемого типа и переданным аргументом, гораздо лучше использовать первое объявление. Клиентский код является более чистым, как указано выше.
Если отношения не существуют, то лучше избегать второй декларации. Наличие возвращаемого типа с ограниченным шаблоном заставляет клиента использовать подстановочные знаки везде, поэтому клиентский код становится взломанным и нечитаемым. Джошуа Блох подчеркивает, что вам следует избегать ограниченных подстановочных знаков в типах возврата (слайд 23). Хотя ограниченные групповые символы в обратных типах могут быть полезны, в некоторых случаях уродство кода результата должно, ИМХО, отменять выгоду.
В этом конкретном случае нет. однако второй вариант более гибкий, поскольку он позволит вам возвращать коллекцию, содержащую элементы другого типа (даже если это также будет Number), чем тип, содержащийся в параметре коллекции.
Конкретный пример:
Collection extends Number> getRoot(Class extends Number> number){ ArrayList result=new ArrayList (); result.add(java.util.Math.round(number); return result) }