Pergunta

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()
Foi útil?

Solução

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.

Outras dicas

As pojo is not declared as a generic

POJO pojo = new POJO();

the compiler assumes you are using it in pre-generic code. i.e. where generics were added after the code was written. So when you do

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

You get a warning rather than an error.

i.e. If the type is non-generic, all generic checks are turn off, not just those which relate to the type you didn't give it. I believe this is for maximum backward compatibility.

For comparison.

Map mapOfInteger = new Map(); // no generics
Set<String> entries = map.entrySet(); // gives a warning, not an error.

In this example, You might expect Set<Entry<K, V>> to become Set<Entry> if not generic, but the compiler falls back to treating the class a non-generic Set.

This is an unchecked assignment that is not treated as error for compatibility reasons.

See Interoperating with Legacy Code

In reality, the assignment is legal, but it generates an unchecked warning.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top