Why won’t this generic java code compile?

Got it. This actually isn’t a bug, strange as it might seem.

From section 4.8 (raw types) of the JLS:

The type of a constructor (§8.8),
instance method (§8.8, §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
erasure of its type in the generic
declaration corresponding to C. The
type of a static member of a raw type
C is the same as its type in the
generic declaration corresponding to
C.

So even though the method’s type signature doesn’t use any type parameters of the class itself, type erasure kicks in and the signature becomes effectively

public Map getMap()

In other words, I think you can imagine a raw type as being the same API as the generic type but with all <X> bits removed from everywhere (in the API, not the implementation).

EDIT: This code:

MyClass unchecked = new MyClass();
Map<String, String> map = unchecked.getMap();  // Unchecked warning, why?
String s2 = map.get("");

compiles because there’s an implicit but unchecked conversion from the raw Map type to Map<String, String>. You can get the same effect by making an explicit conversion (which does nothing at execution time) in the last case:

// Compiles, but with an unchecked warning
String x = ((Map<String, String>)fail.getMap()).get("");

Leave a Comment