Обобщения в Java: часть 1 - Нижние пределы
ОГЛАВЛЕНИЕ
Нижние пределы
Рассмотрим последний пример. Допустим, надо скопировать элементы из одной коллекции в другую. Ниже приведен код первой попытки сделать это:
public static <T> void copy(Collection<T> from, Collection<T> to) {…}
Попытаемся использовать данный метод:
ArrayList<Dog> dogList1 = new ArrayList<Dog>();
ArrayList<Dog> dogList2 = new ArrayList<Dog>();
//…
copy(dogList1, dogList2);
В этом коде копируются Dog из одного Dog ArrayList в другой. Поскольку Dog является Animal, Dog может находиться в Dog ArrayList и в Animal ArrayList, не так ли? Следующий код копирует из Dog ArrayList в Animal ArrayList.
ArrayList<Animal> animalList = new ArrayList<Animal>();
copy(dogList1, animalList);
Однако при компиляции этого кода выдается ошибка:
Error:
line (36) <T>copy(java.util.Collection<T>,java.util.Collection<T>)
in com.agiledeveloper.Test cannot be applied
to (java.util.ArrayList<com.agiledeveloper.Dog>,
java.util.ArrayList<com.agiledeveloper.Animal>)
Как заставить его работать? Здесь помогают нижние пределы. Второй аргумент Copy должен иметь тип T или любой тип, являющийся базовым типом T. Код выглядит так:
public static <T> void copy(Collection<T> from, Collection<? super T> to)
Здесь сказано, что принимаемый второй коллекцией тип является типом T или его супертипом.
Заключение
На примерах была показана мощь обобщений в Java. Однако с использованием обобщений в Java есть проблемы, которые будут рассмотрены в части II данной статьи. В части II будут разобраны некоторые ограничения обобщений, реализация обобщений в Java, эффект стирания типа, изменения в библиотеке классов Java ради обеспечения обобщений, проблемы преобразования необобщенного кода в обобщенный код, и, наконец, некоторые из подводных камней или недостатков обобщений.
В части I были рассмотрены принципы обобщений в Java и их применение. Обобщения обеспечивают безопасность типов. Обобщения реализованы так, чтобы обеспечить обратную совместимость с необобщенным кодом. Они проще шаблонов в C++ и не вызывают раздувания кода при компиляции. В части II разбираются проблемы применения обобщений.