使用ECJ的Lambda /默认方法/类型擦除怪癖/错误?

时间:2015-06-25 11:33:00

标签: java lambda java-8 type-erasure default-method

今天遇到了这个问题,花了很多时间试图重现/弄清楚发生了什么。有人可以解释为什么会发生这种情况,或者这是类型擦除/默认方法/ lambda / polymorphism的错误?取消注释默认方法可以使它运行正常,但我希望这可以按原样运行

输出:

Works fine with an object
Calling consume
Hello
Calling accept with context
Hello
Calling accept via consumer...
Exception in thread "main" java.lang.AbstractMethodError: Method test/LambdaTest$$Lambda$1.accept(Ljava/lang/Object;)V is abstract
    at test.LambdaTest$$Lambda$1/834600351.accept(Unknown Source)
    at test.LambdaTest.main(LambdaTest.java:24)

代码

package test;

import java.util.function.Consumer;

public class LambdaTest {

    public static void main(String[] args) {
        Consumer<Context> contextIgnoringObject = new ContextUnawareObject();
        contextIgnoringObject.accept(new Context());

        ContextIgnorer contextIgnoringLambda = () -> {
            System.err.println("Hello");
        };

        System.err.println("Calling consume");
        contextIgnoringLambda.consume();

        System.err.println("Calling accept with context");
        contextIgnoringLambda.accept(new Context());

        Consumer<Context> consumer = contextIgnoringLambda;

        System.err.println("Calling accept via consumer...");
        consumer.accept(new Context());

    }

    @FunctionalInterface
    public interface ContextIgnorer extends Consumer<Context> {

//      default void accept(Object object) {
//          System.err.println("Manual bridge method");
//          accept((Context)object);
//      }

        @Override
        default void accept(Context context) {
            consume();
        }

        void consume();

    }

    public static class ContextUnawareObject implements ContextIgnorer {

        @Override
        public void consume() {
            System.err.println("Works fine with an object");
        }

    }

    public static class Context {

    }

}

1 个答案:

答案 0 :(得分:1)

旧版ECJ编译器(3.10.0)出现问题:

$ java -jar org.eclipse.jdt.core-3.10.0.v20140604-1726.jar -source 1.8 LambdaTest.java 
$ java LambdaTest
Works fine with an object
Calling consume
Hello
Calling accept with context
Hello
Calling accept via consumer...
Exception in thread "main" java.lang.AbstractMethodError: Method LambdaTest$$Lambda$1.accept(Ljava/lang/Object;)V is abstract
    at LambdaTest$$Lambda$1/424058530.accept(Unknown Source)
    at LambdaTest.main(LambdaTest.java:24)

使用org.eclipse.jdt.core_3.10.0.v20140902-0626.jar或更新版解决了这个问题。 Oracle javac编译器没有这样的问题。因此,解决方案是更新您的ECJ编译器或转移到javac。