В чем разница между ограниченным символом подстановки и параметрами типа? - PullRequest
37 голосов
/ 17 ноября 2009

Есть ли разница между

<N extends Number> Collection<N> getThatCollection(Class<N> type)

и

Collection<? extends Number> getThatCollection(Class<? extends Number>)

Ответы [ 2 ]

36 голосов
/ 17 ноября 2009

Они предоставляют различные интерфейсы и контракт для метода.

Первое объявление должно возвращать коллекцию, тип элементов которой совпадает с классом аргумента. Компилятор выводит тип N (если не указан). Поэтому следующие два оператора действительны при использовании первого объявления:

Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);

Во втором объявлении не объявляется связь между возвращенным аргументом типа Collection и классом аргумента. Компилятор предполагает, что они не связаны, поэтому клиент должен будет использовать возвращаемый тип как 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). Хотя ограниченные подстановочные знаки в возвращаемых типах могут быть полезны в некоторых случаях, уродливость кода результата, IMHO, должна перевесить преимущество.

0 голосов
/ 17 ноября 2009

В данном конкретном случае нет. однако вторая опция более гибкая, поскольку она позволяет вам возвращать коллекцию, которая содержит элементы другого типа (даже если это будет также Number), чем тип, содержащийся в параметре коллекции.

Конкретный пример:

Collection<? extends Number> getRoot(Class<? extends Number> number){ 
    ArrayList<Integer> result=new ArrayList<Integer>();
    result.add(java.util.Math.round(number); 
    return result) 
}
...