Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generic Type Inference Strange Behavior?

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.

like image 796
pathikrit Avatar asked Jun 05 '26 09:06

pathikrit


1 Answers

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.

like image 59
Perception Avatar answered Jun 07 '26 22:06

Perception