【发布时间】:2016-03-05 16:42:41
【问题描述】:
我有这个(看似)无辜的代码(在这里简化为这个 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<String, Number> createMap() {
if (doFail) {
throw new IllegalArgumentException();
}
return new HashMap<>();
}
public static <T> T get(final Callable<T> _valueCreator, final Supplier<T> _errorValue) {
try {
return _valueCreator.call();
} catch (final Exception e) {
return _errorValue.get();
}
}
public static Map<String, Number> 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()));
}
}
问题出在return 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.String,java.lang.Number>,java.lang.Object
我认为从返回类型 (Map<String, Number>) 以及 createMap (相同) 的签名中都应该可以推断出所需的类型 - 事实上似乎 Eclipse 编译器似乎能够做到。但是,JDK 编译器只推断Map<Object, Object>,因此会失败。
这是 JDK 错误还是 Eclipse 编译器错误或其他什么?
【问题讨论】:
-
他们似乎已经修复了它。我刚刚做了一些实验。它使用
javac 1.8.0_65编译,但不使用javac 1.8.0_25。我懒得找到修复这个问题的确切版本。 -
它不能在 Ideone 上编译。 ideone.com/UDHTXm
-
@PaulBoddington 谢谢,我会试试的。我们有 1.8.0_51,所以它似乎是最近的修复。
标签: java eclipse generics compiler-errors