2015-06-25 10 views
5

今天來到這裏,花了許多時間試圖重現/弄清楚發生了什麼。有人可以解釋爲什麼會發生這種情況,或者這是一個類型擦除/默認方法/ lambda的/多態性的錯誤?在取消的默認方法使得它運行良好,但我本來期望這個工作,因爲是使用ECJ的Lambda /默認方法/類型擦除怪癖/錯誤?

輸出:

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 { 

    } 

} 
+3

提供的代碼適合我。我編譯使用javac 1.8.0.25,1.8.0.40和ecj,使用java 1.8.0.25和1.8.0.40啓動。在所有這些情況下,我都沒有看到任何例外。你正在使用哪個編譯器版本?清理項目可能會有幫助嗎? –

+2

肯定是一個編譯器錯誤。當你說取消註釋'default'方法解決問題時,這變得尤其明顯,因爲編譯器應該*拒絕'default'方法,因爲它與其他'accept'方法的擦除相沖突(以及編譯器的橋接方法應該產生)。更新你的編譯器... – Holger

+0

嗯,我編譯並運行.25,.45和.60ea b19,他們都失敗了我。在Windows x64上運行。 –

回答

1

這個問題似乎與舊的歐洲法院編譯器(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。