注:我發現了多個指出javac
與Eclipse編譯器之間差異的問題,但據我所見,他們都討論了其他問題。泛型和lambdas - 在javac和Eclipse編譯器中的不同行爲
假設我們有這樣的方法:編譯調用此方法的時候,我不知道哪兩個是正確
public static <T, U> void foo(Supplier<T> a, Function<T, U> b, Consumer<U> c)
{
c.accept(b.apply(a.get()));
}
我發現javac
之間不同的行爲和Eclipse Java編譯器。
一個簡單的使用這種方法可以是:
// variant 1
foo(
() -> Optional.of("foo"),
value -> value.get(),
value -> System.out.println(value));
編譯器應該能夠使用第一參數和U
使用第二結合T
到Optional<String>
到String
。所以這個電話應該是有效的(在我看來)。
編譯沒有使用javac
,但無法使用Eclipse編譯:
類型不匹配:不能從空轉變爲<未知>
添加一個類型參數的第一個參數(() -> Optional.<String> of("foo")
)也使它在Eclipse中編譯。
問題:從規範的角度來看,Eclipse拒絕這個調用是否正確(以及爲什麼(不))?
現在假設我們想拋出一個自定義(運行時)例外,如果Optional
爲空:
// variant 2
foo(
() -> Optional.of("foo"),
value -> value.orElseThrow(() -> new RuntimeException()),
value -> System.out.println(value));
這是由雙方拒絕,javac
和Eclipse編譯器,但使用不同的錯誤信息:
javac
: 「沒有報告異常X;必須捕獲或聲明拋出」- Eclipse的編譯器:「類型不匹配:不能從空轉變爲<未知>」
當我添加類型參數的第一個參數如上,Eclipse的成功編制,同時javac
仍然失敗。當我在第二個參數中添加<RuntimeException>
作爲類型參數時,反過來,Eclipse失敗並javac
成功。
問題:再說一次,編譯器是否有權拒絕這個調用,爲什麼?
在我看來,這兩個變種應該編譯罰款沒有額外的提示通過使用類型參數。如果是這樣,我將爲javac
(關於「未報告的異常」)和Eclipse編譯器(關於「類型不匹配」)填寫一個錯誤報告。但首先我想確保規範與我的觀點一致。
版本中使用:
javac
:1.8.0_66- 的Eclipse JDT:3.11.1.v20151118-1100
編輯:
我填針對Eclipse中的問題的bug 482781。
與javac
的問題已被報告爲JDK-8056983,請參閱Tunakis answer。
有疑問時會責怪日食:)類型推斷非常複雜,整個lambda語法還是相當新的。 Eclipse有幾個修正的錯誤,但是在當前的發行版中留下了一些錯誤,與此類邊緣案例有關。 – zapl
當涉及到通用擴展時,Eclipse Mars ECJ編譯器與最新的Luna相比確實很麻煩。當ECJ 3.11失敗或者甚至陷入無限循環而javac和ECJ 3.10編譯正確時,我已經發現至少有三種情況。這就是爲什麼我還在使用Luna。 –
Eclipse bug已經通過https://bugs.eclipse.org/470826修復了4.6 M1,它也被安排到mars.2的back端口 –