Search code examples
javaoopgenericstypestype-safety

Java compiler ignores type safety


public class POJO<T> {

    private List<Integer> integer = new ArrayList<Integer>();

    public POJO() {
        integer.add(1);
        integer.add(2);
    }

    public List<Integer> getInteger() {
        return integer;
    }

    public static void main(String[] args) {
        POJO pojo = new POJO();
        List<String> integer = pojo.getInteger(); // No compile error?
        System.out.println(integer); // prints [1, 2]
    }
}

How is it possible for the following line to compile:

List<String> integer = pojo.getInteger();

Provided getInteger() is typed as following

public List<Integer> getInteger()

Solution

  • I found a reference in the JLS 4.8 that backs up what @PeterLawrey says:

    The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.

    So all instance methods of your raw POJO object are erased, including those that don't reference the type T of POJO<T>, which means (JLS 4.6):

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