Search code examples
javagenericsscjpocpjp

Java Generics - Why is this method call considered an unchecked conversion


The following code examples compiles but with a compiler warning

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");
    }
}   

When i compile the above i get the following warning

Note: ZiggyTest2.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Or if i compile it with -Xlint:unchecked i get the following warning

ZiggyTest2.java:12: warning: [unchecked] unchecked conversion
found   : SubArrayList<Animal>
required: java.util.ArrayList<Animal>
                ArrayList<Animal> nums = new SubArrayList<Animal>();
                                         ^
1 warning

If i change the initialisation of nums to

List<Animal> nums = new ArrayList<Animal>(); 

then i dont get any warnings.

Why are they behaving differently. ArrayList is a subtype of List and SubArrayList is a subtype of ArrayList so i was expecting the instantiation to be the same.

Thanks.

Edit

Also if i call the method and pass it an reference initialised generically it also produces a warning.

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");
    }
}

I thought compiler warnings will only appear if you mix generic code with non-generic code.


Solution

  • Your SubArrayList<T> class only extends ArrayList (essentially ArrayList<?>), and not ArrayList<T>, making a cast from SubArrayList<T> to ArrayList<T> unchecked.

    If you change it to class SubArrayList<T> extends ArrayList<T> {}, you will not have the problem anymore :)