Есть ли разница между
<N extends Number> Collection<N> getThatCollection(Class<N> type)
и
Collection<? extends Number> getThatCollection(Class<? extends Number>)
Есть ли разница между
<N extends Number> Collection<N> getThatCollection(Class<N> type)
и
Collection<? extends Number> getThatCollection(Class<? extends Number>)
Они выставляют разные интерфейсы и заключают контракт для этого метода.
Первое объявление должно возвращать коллекцию, тип элементов которой совпадает с классом аргументов. Компилятор указывает тип N
(если не указан). Таким образом, следующие два утверждения действительны при использовании первого объявления:
Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);
Второе объявление не объявляет связь между возвращаемым аргументом типа коллекции классу аргументов. Компилятор предполагает, что они не связаны между собой, поэтому клиенту придется использовать возвращаемый тип как Collection<? extends Number>
, независимо от того, что аргумент:
// Invalid statements
Collection<Integer> c1 = getThatCollection(Integer.class); // invalid
Collection<Double> c2 = getThatCollection(Double.class); // invalid
Collection<Number> 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<Integer> result=new ArrayList<Integer>();
result.add(java.util.Math.round(number);
return result)
}