Reputation:
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()
Upvotes: 7
Views: 208
Reputation: 26180
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.
Upvotes: 2
Reputation: 328598
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.
Upvotes: 6
Reputation: 533502
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
.
Upvotes: 6