2017-07-03 68 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

感谢您的输入。这似乎是支持所有相关编译器的最小创新改变。 –