today I have ran into strange javac
behavior regarding generic type inference. Here's example class to ilustrate this strange behavior:
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
public class Test {
protected <T> T strange(T t, Map<String, String> map) {
return t;
}
protected void ok(Map<String, String> map) {}
protected <T> T test(T t) {
T res = strange(t , new HashMap<String, String>());
//Doesn't work
//res = strange(t, new <String, String>HashMap());
ok(new <String, String>HashMap());
res = strange(t, Collections.<String, String>emptyMap());
//Doesn't work
//res = strange(t, Collections.EMPTY_MAP);
res = strange(t, (Map<String, String>) Collections.EMPTY_MAP);
ok(Collections.EMPTY_MAP);
return res;
}
}
Notice //Doesn't work
comments. If you uncomment this code you will get strange compiler error:
Test.java:18: error: incompatible types
res = strange(t, Collections.EMPTY_MAP);
^
required: T
found: Object
where T is a type-variable:
T extends Object declared in method <T>test(T)
Strange thing is that error complains about strange
method return type is Object and not T, but when second unsafe parameter is cast to correct type then T is inferred correctly.
Can someone explain if this is correct behavior? Because it looks strange to me. Can it be a compiler bug?
Why this line works
T res = strange(t , new HashMap<String, String>());
and this one is doesn't?
T res = strange(t, new <String, String>HashMap());
I have tested it with java 7 and 6.