Question

Consider te following code:

public class MyClass<T>{
    T data;
    public MyClass(T data){ this.data=data; }
}
public class Main{
    public static void main(String[] args){
        MyClass m= new MyClass<Integer>(3);// ok

    }
}

I read "What is a raw type and why shouldn't we use it?" topic. Hence, if we have a parameterized type MyClass<T> then by defenition of raw type we can define reference MyClass m to raw type at compile time. Moreover raw type MyClass, corresponding to given parameterized type MyClass<T> is superclass of MyClass<E> at compile time before type erasure for all specific type E. Does this reason correct?

Was it helpful?

Solution

From Angelika Langer's Generics FAQ:

raw types are supertypes of all concrete and all wildcard instantiations of the generic type. For instance, the raw type Collection is a supertype of all instantiations of the generic type Collection.

generic type hierarchy

The article continues:

Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. That is, every instantiation of a generic type can be converted to the corresponding raw type. The reverse is permitted, too, for reasons of compatibility between generic and non-generic types. It is the so-called unchecked conversion and is accompanied by an "unchecked" warning.

To address your further questions in the comment:

In the case of raw type: List lst= new ArrayList() what compiler is doing? There is no type for checking and erasure?

There's no generic type checking. Obviously the compiler still makes sure ArrayList is assignable to List. Nothing generics-specific is happening here - code like this would've typically been written prior to generics being added to the language. Now, it's still allowed for backward compatibility, but the compiler will warn you about using raw types.

And why List lst= new ArrayList<String>() and List<Integer> lst= new ArrayList() is correct?

It's only correct in that it successfully compiles but it isn't best practice and will cause compiler warnings for both using raw types and unchecked conversion.

Does it mean that raw type is supertype and subtype for all generic types at compile time before type erasure?

As pointed out by the Generics FAQ a raw type is the supertype of all its generic variations. The reason the assignment is allowed both ways is that raw types "opt out" of generic type checking, so using them on either side of the assignment implicitly does an unchecked conversion. Once again, the compiler will warn you about this, since it threatens type safety.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top