I have this (seemingly) innocent code (simplified into this JUnit test case here):
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()));
}
}
The problem lies in the line return get(GenericsTest::createMap, Collections::emptyMap)
: the Eclipse compiler doesn't see a problem here (and so am I), happily compiles and runs the test and succeeds.
However, when I compile this on the command line (Maven 3, Oracle JDK8 in this case, but also doesn't work with javac directly), a compile error is thrown:
.../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
I would think that from both the return type (Map<String, Number>
) as well as from the signature of createMap
(same) it should be possible to infer the required type - and in fact it seems that the Eclipse compiler seems to be able to do it. However, the JDK compiler only infers Map<Object, Object>
and thus fails.
Is this a JDK bug or an Eclipse compiler bug or something else?
This looks like a bug. I will take care of it and probably add a better answer once we have more information about why this is happening. I have filed this bug entry JDK-8043926 to track it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With