2015-12-01 73 views
5

我有這個(貌似)無辜的代碼(簡化成這個JUnit測試案例在這裏):爲什麼Oracle Java編譯器不能在此推斷邊界,但Eclipse可以?

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,甲骨文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編譯器錯誤或其他東西?

+2

他們似乎已經修復它。我剛剛做了一些實驗。它使用'javac 1.8.0_65'編譯,但不使用'javac 1.8.0_25'。我懶得找到確切的釋放,這是固定的。 –

+0

它不在Ideone上編譯。 https://ideone.com/UDHTXm –

+0

@PaulBoddington謝謝,我會嘗試。我們有1.8.0_51,所以它似乎是最近的修復。 –

回答

1

確實是一個bug,相同的代碼編譯與JDK 1.8.0u66很好,但沒有我以前有1.8.0u51編譯。

3

這看起來像一個錯誤。我會照顧它,並且一旦我們有更多關於這種情況發生的信息,可能會添加更好的答案。我已經提交了這個bug條目JDK-8043926來跟蹤它。

相關問題