Can someone explain this behaviour to me:
Note: That T is never used in SomeThingGeneric
public static class SomeThingGeneric<T> {
public List<String> getSomeList() {
return null;
}
}
final SomeThingGeneric<Object> someThingGenericObject = new SomeThingGeneric<Object>();
final SomeThingGeneric<?> someThingGenericWildcard = new SomeThingGeneric<Object>();
final SomeThingGeneric someThingGenericRaw = new SomeThingGeneric<Object>();
for (final String s : someThingGenericObject.getSomeList()) { } // 1 - compiles
for (final String s : someThingGenericWildcard.getSomeList()) { } // 2 - compiles
for (final String s : someThingGenericRaw.getSomeList()) { } // 3 - does not compile!
(1) and (2) compiles but (3) fails with following message:
incompatible types
found : java.lang.Object
required: java.lang.String
If anyone wants the full code, here it is. I have verified this in both Java 5 and 6.
Well, this is an interesting question despite the downvotes. I believe the answer to the question lies in this portion of the JLS:
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.
Effectively, your method public List<String> getSomeList gets an effective signature of public List getSomeList, in the scenario where you accessing it via a raw type. And as such, the list iterator for the resulting list then 'returns' objects instead of strings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With