Что является различием между этим объявлением метода:
public static <E extends Number> List<E> process(List<E> nums){
и
public static List<Number> process(List<Number> nums){
Где Вы использовали бы первого?
Первый позволяет обрабатывать
List
, List
и т.д. Второй - нет.
Дженерики в Java инвариантны. Они не ковариантны, как массивы.
То есть, в Java Double[]
является подтипом Number[]
, но List
НЕ является подтипом List
. List
, однако, является List extends Number>
.
Есть веские причины для того, чтобы дженерики были инвариантными, но именно поэтому типы extends
и super
часто необходимы для гибкости подтипирования.
super
и extends
для ограниченных подстановочных знаковextends
Consumer super
" Последний метод (метод без
) принимает только параметр точно типа List
, и всегда ли он будет
возвращать List
. Например, он не примет List
.
Предыдущий метод (метод с
) является общим методом , то есть он может принимать различные типы List
s
, и он вернет тот же тип List
, если List
s являются списками чего-то что
расширяет число
, например Список <Целое число>
.
Пример:
import java.util.ArrayList;
import java.util.List;
public class ProcessGenerics {
List<Number> listNumber = new ArrayList<Number>();
List<Integer> listInteger = new ArrayList<Integer>();
List<Double> listDouble = new ArrayList<Double>();
public static
List<Number> processWithoutExtends(List<Number> nums){ return nums; }
List<Number> resultN = processWithoutExtends(listNumber); // OK
//List<Integer> resultI = processWithoutExtends(listInteger); // compile-error - method not applicable
//List<Double> resultD = processWithoutExtends(listDouble); // compile-error - method not applicable
public static <E extends Number>
List<E> processWithExtends(List<E> nums){ return nums; }
List<Number> resultN2 = processWithExtends(listNumber); // OK
List<Integer> resultI2 = processWithExtends(listInteger); // OK
List<Double> resultD2 = processWithExtends(listDouble); // OK
}
См. Аналогичное объяснение в главе «Подстановочные знаки» в Уроке по обобщениям в учебных пособиях по Java:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping. html
См. также Как преобразовать список наследуемых объектов в коллекцию объектов в Java? Оба вопроса действительно касаются обобщений и подтипов, например является ли List
подтипом List
(это не так !!!).