javagenericsintellij-idea

Raw Type with List<String> gives compilation error


I have the following Generic class:

import java.util.ArrayList;
import java.util.List;

public class GenericRaw<T> {
    public List<String> get() {
         return new ArrayList<>();
    }
}

Let us consider the case of its usage:

public class Usage {
    public void doSomething() {
        GenericRaw base = new GenericRaw();
        for (String x : base.get()) {   }
    }
}

For this code Idea doesn't give any compilation error but Java compiler itself does:

java: incompatible types required: java.lang.String found: java.lang.Object

Reproducible on JDK 1.6.0_33 as well as on JDK 1.7.0_17.

Can someone help me with the explanation of this issue?

Results of my investigations. The following variants can be successfully compiled:

public void doSomething() {
    GenericRaw<?> base = new GenericRaw();
    for (String x : base.get()) {   }
}

or even:

public void doSomething() {
    GenericRaw base = new GenericRaw();
    List<String> list = base.get();
    for (String x : list) {   }
}

Solution

  • Can someone help me with the explanation of this issue?

    Sure. It's following the JLS's description of raw types, in section 4.8:

    To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.

    The erasure of GenericRaw<T> is:

    public class GenericRaw {
        public List get() { ... }
    }
    

    because:

    Type erasure also maps the signature (§8.4.2) of a constructor or method to a signature that has no parameterized types or type variables. The erasure of a constructor or method signature s is a signature consisting of the same name as s and the erasures of all the formal parameter types given in s.

    The type parameters of a constructor or method (§8.4.4), and the return type (§8.4.5) of a method, also undergo erasure if the constructor or method's signature is erased.