2017-07-03 69 views
3

使用某些現有代碼時,在運行代碼時遇到了一個問題,其代碼爲Eclipse Neon.3。不幸的是,我沒能重現最小工作示例的異常,但下面的輸出是由類加載器生產:Eclipse:在類型推斷過程中出現「未知錯誤」

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack 
Exception Details: 
    Location: 
    ... 
    Reason: 
    Type 'java/lang/Object' (current frame, stack[8]) is not assignable to 'MyMap' 
    Current Frame: 
    ... 
    Bytecode: 
    ... 
    Stackmap Table: 
    ... 

它可以在命令行和中老年的Eclipse版本,所以這並不重要當時很多。上週,Eclipse Oxygen.1已經發布,我們開始使用那個。現在,同樣的代碼產生一個編譯時異常:

Problem detected during type inference: Unknown error at invocation of reduce(Main.MyMap<MyKey,MyValue>, BiFunction<Main.MyMap<MyKey,MyValue>,? super MyValue,Main.MyMap<MyKey,MyValue>>, BinaryOperator<Main.MyMap<MyKey,MyValue>>) 

我已經成功地放在一起,產生這個錯誤在Eclipse中,但工作在命令行上最小的工作例如:

import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Set; 

public class Main<MyKey, MyValue> { 

    static class MyMap<K, V> extends HashMap<K, V> { 
     public MyMap<K, V> putAllReturning(MyMap<K, V> c) { putAll(c); return this; } 
     public MyMap<K, V> putReturning(K key, V value) { put(key, value); return this; } 
    } 

    public Main() { 
     Set<MyValue> values = new HashSet<>(); // actually something better 
     final MyMap<MyKey, MyValue> myMap = 
       values.stream() 
        .reduce(
         new MyMap<MyKey, MyValue>(), 
         (map, value) -> { 
          Set<MyKey> keys = new HashSet<>(); // actually something better 

          return keys.stream() 
           .reduce(
            map, // this would work syntactically: new MyMap<MyKey, MyValue>(), 
            (map2, key) -> map2.putReturning(key, value), 
            MyMap::putAllReturning); 
         }, 
         MyMap::putAllReturning 
        ); 
    } 
} 

它似乎內部減少的第一個參數會導致類型推斷中斷,因爲用同一類型的另一個實例(但顯式聲明而不是推斷)替換它會消除錯誤。

知道類中錯誤的確切來源使我們能夠重寫代碼(將傳遞給外部reduce的lambda表達式提取到自己的方法中)。不過,我仍然有興趣解釋爲什麼這樣的構造可能會破壞兩個較新的eclipse編譯器。

+1

除了Eclipse的問題,這個代碼是無論如何打破。您應該瞭解[減少](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Reduction)和[可變減少](https: //docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction)或[identity value]的含義(https://stackoverflow.com/a/ 32867283/2711488),要求作爲['reduce']的第一個參數(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-U-java。 util.function.BiFunction-java.util.function.BinaryOperator-)... – Holger

+0

感謝您的示例,請參閱https://bugs.eclipse.org/519147 –

+1

事實證明,這個問題是由於ECJ模仿javac的長期存在的bug https://bugs.openjdk.java.net/browse/JDK-8026527 - 由於顯而易見的原因,沒有精確的規範。固定用於Photon M5。 –

回答

3

很適合我的Oxygen,它的工作通過簡單地聲明參數的減少:

(MyMap<MyKey, MyValue> map, MyValue value) -> .... 

知道了確切問題,爲什麼日食編譯器無法推斷類型是我太重要了;無論如何這應該被報告(它可能已經被日食團隊知道)。

我也可以確認其編譯OK與jdk-8-131jdk-9-175

+0

感謝您的輸入。這似乎是支持所有相關編譯器的最小創新改變。 –