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.

Другие вопросы по тегам