Why won't this generic java code compile?
generics, java
Solution
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("");
Problem
In this simplified example I have a generic class, and a method that returns a Map regardless of the type parameter. Why does the compiler wipe out the types on the map when I don't specify a type on the containing class? ``` import java.util.Map; public class MyClass<T> { public Map<String, String> getMap() { return null; } public void test() { MyClass<Object> success = new MyClass<Object>(); String s = success.getMap().get(""); MyClass unchecked = new MyClass(); Map<String, String> map = unchecked.getMap(); // Unchecked warning, why? String s2 = map.get(""); MyClass fail = new MyClass(); String s3 = fail.getMap().get(""); // Compiler error, why? } } ``` I get this compiler error. ``` MyClass.java:20: incompatible types found : java.lang.Object required: java.lang.String String s3 = fail.getMap().get(""); // Compiler error ```