Lambda/default methods/type 使用 ECJ 擦除 quirk/bug?
Lambda/default methods/type erasure quirk/bug using ECJ?
今天遇到这个问题,花了很长时间试图 reproduce/figure 弄清楚到底发生了什么。有人可以解释为什么会发生这种情况,或者这是 erasure/default methods/lambda's/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.accept(Ljava/lang/Object;)V is abstract
at test.LambdaTest$$Lambda/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 {
}
}
问题出现在较旧的 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.accept(Ljava/lang/Object;)V is abstract
at LambdaTest$$Lambda/424058530.accept(Unknown Source)
at LambdaTest.main(LambdaTest.java:24)
使用 org.eclipse.jdt.core_3.10.0.v20140902-0626.jar 或更新版本可以解决问题。 Oracle javac 编译器没有这个问题。因此解决方案是更新您的 ECJ 编译器或移动到 javac.
今天遇到这个问题,花了很长时间试图 reproduce/figure 弄清楚到底发生了什么。有人可以解释为什么会发生这种情况,或者这是 erasure/default methods/lambda's/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.accept(Ljava/lang/Object;)V is abstract
at test.LambdaTest$$Lambda/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 {
}
}
问题出现在较旧的 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.accept(Ljava/lang/Object;)V is abstract
at LambdaTest$$Lambda/424058530.accept(Unknown Source)
at LambdaTest.main(LambdaTest.java:24)
使用 org.eclipse.jdt.core_3.10.0.v20140902-0626.jar 或更新版本可以解决问题。 Oracle javac 编译器没有这个问题。因此解决方案是更新您的 ECJ 编译器或移动到 javac.