Lambda/default methods/type erasure quirk/bug using ECJ?

303 views Asked by At

Came accross this today and spent ages trying to reproduce/figure out what was happening. Can somebody explain why this happens or is this a bug with type erasure/default methods/lambda's/polymorphism? Uncommenting the default method makes it run fine, but I would have expected this to work as is

Output:

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)

Code

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

There are 1 answers

0
Tagir Valeev On BEST ANSWER

The problem appears with older ECJ compiler (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)

Using org.eclipse.jdt.core_3.10.0.v20140902-0626.jar or newer solves the problem. The Oracle javac compiler has no such problem. Thus the solution would be to update your ECJ compiler or move to the javac.