我有这个(貌似)无辜的代码(在这里简化为这个JUnit测试用例):
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import org.junit.Test;
public class GenericsTest {
private static boolean doFail;
private static Map createMap() {
if (doFail) {
throw new IllegalArgumentException();
}
return new HashMap<>();
}
public static T get(final Callable _valueCreator,final Supplier _errorValue) {
try {
return _valueCreator.call();
} catch (final Exception e) {
return _errorValue.get();
}
}
public static Map getCachedMap() {
return get(GenericsTest::createMap,Collections::emptyMap);
}
@Test
public void testSuccess() {
doFail = false;
assertThat(getCachedMap(),instanceOf(HashMap.class));
}
@Test
public void testFail() {
doFail = true;
assertThat(getCachedMap(),instanceOf(Collections.EMPTY_MAP.getClass()));
}
}
问题在于行返回get(GenericsTest :: createMap,Collections :: emptyMap):Eclipse编译器在这里看不到问题(我也是如此),愉快地编译并运行测试并成功.
但是,当我在命令行(Maven 3,在这种情况下为Oracle JDK8,但也不能直接使用javac)上编译它时,会抛出编译错误:
.../GenericsTest.java:[23,19] incompatible types: inferred type does not conform to upper bound(s)
inferred: java.util.Map extends java.lang.Object,? extends java.lang.Object>
upper bound(s): java.util.Map,java.lang.Object
我认为,从返回类型(Map< String,Number>)以及createMap的签名(相同),应该可以推断出所需的类型 – 实际上似乎Eclipse编译器似乎是能够做到这一点.但是,JDK编译器仅推断Map< Object,Object>因此失败了.
这是JDK错误还是Eclipse编译器错误或其他什么?