2015-06-25 5 views
5

Kam heute darüber hinweg und verbrachte Ewigkeiten damit, zu reproduzieren/herauszufinden, was vor sich ging. Kann jemand erklären, warum das passiert oder ist das ein Bug mit type radition/default methods/lambda's/polymorphism? die Standardmethode uncommenting macht es gut laufen, aber ich würde dies alsLambda/Standard-Methoden/Typ löschen Quirk/Bug mit ECJ?

ist

Output arbeiten zu erwarten:

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 { 

    } 

} 
+3

Der mitgelieferte Code funktioniert gut für mich. Ich kompilierte mit javac 1.8.0.25, 1.8.0.40 und ecj, gestartet mit Java 1.8.0.25 und 1.8.0.40. In all diesen Fällen sehe ich keine Ausnahme. Welche Compiler-Version verwendest du? Wahrscheinlich würde das Reinigen des Projekts helfen? –

+2

Sicherlich ein Compiler Bug. Das wird besonders offensichtlich, wenn Sie sagen, dass das Auskommentieren der 'default'-Methode das Problem behebt - da der Compiler * diese' default'-Methode ablehnen sollte, da sie mit der Löschung der anderen 'accept'-Methode kollidiert (und der Bridge-Methode des Compilers) sollte generieren). Aktualisieren Sie Ihren Compiler ... – Holger

+0

Hm Ich habe kompiliert und lief mit .25, .45 und .60ea b19, sie alle für mich gescheitert. Wird unter Windows x64 ausgeführt. –

Antwort

1

Das Problem mit älteren EuGH-Compiler (3.10 erscheint. 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) 

Mit org.eclipse.jdt.core_3.10.0.v20140902-0626.jar oder neuem Sol Ves das Problem. Der Oracle Javac Compiler hat kein solches Problem. Daher wäre die Lösung, Ihren ECJ-Compiler zu aktualisieren oder zum javac zu wechseln.