Java Generics - Почему этот вызов метода считается непроверенным преобразованием
Следующие примеры кода компилируются, но с предупреждением компилятора
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
class SubArrayList<T> extends ArrayList{}
class ZiggyTest2{
public static void main(String[] args){
ArrayList<Animal> nums = new SubArrayList<Animal>();
}
public static void testMethod(ArrayList<Animal> anim){
System.out.println("In TestMethod");
}
}
Когда я компилирую выше, я получаю следующее предупреждение
Note: ZiggyTest2.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Или, если я скомпилирую это с -Xlint:unchecked я получу следующее предупреждение
ZiggyTest2.java:12: warning: [unchecked] unchecked conversion
found : SubArrayList<Animal>
required: java.util.ArrayList<Animal>
ArrayList<Animal> nums = new SubArrayList<Animal>();
^
1 warning
Если я изменю инициализацию чисел на
List<Animal> nums = new ArrayList<Animal>();
тогда я не получаю никаких предупреждений.
Почему они ведут себя по-разному. ArrayList является подтипом List, а SubArrayList является подтипом ArrayList, поэтому я ожидал, что экземпляр будет таким же.
Благодарю.
редактировать
Также, если я вызываю метод и передаю ему ссылку, инициализированную в общем, это также выдает предупреждение.
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
class SubArrayList<T> extends ArrayList{}
class ZiggyTest2{
public static void main(String[] args){
SubArrayList<Animal> nums = new SubArrayList<Animal>();
testMethod(nums);
}
public static void testMethod(ArrayList<Animal> anim){
System.out.println("In TestMethod");
}
}
Я думал, что предупреждения компилятора появятся, только если вы смешаете универсальный код с неуниверсальным кодом.
3 ответа
Ваш SubArrayList<T>
класс только расширяется ArrayList
(по существу, ArrayList<?>
), и не ArrayList<T>
, делая бросок из SubArrayList<T>
в ArrayList<T>
бесконтрольно.
Если вы измените его на class SubArrayList<T> extends ArrayList<T> {}
, у вас больше не будет проблем:)
Добавить <T>
в ваш ArrayList как в
class SubArrayList<T> extends ArrayList<T>{}
List
это интерфейс, а не класс. ArrayList не является подклассом List, а просто классом, который реализует интерфейс List. SubArrayList, однако, является подклассом ArrayList.