2014-05-15 41 views
7

我这样做:Lambda只能与功能界面一起使用吗?

public class LambdaConflict 
{ 
    public static void main(String args[]){ 
     //* 
     System.out.println(LambdaConflict.get(
      (str) -> "Hello World!! By ME?" 
     )); 
     /*/ 
     System.out.println(LambdaConflict.get(new Intf<String>(){ 
      @Override public String get1(String str){ 
       return "Hello World!! By get1 " + str; 
      } 
     })); 
     /*****/ 
    } 

    public static String get(Intf<String> i, boolean b){ 
     return i.get1("from 1"); 
    } 
} 

interface Intf<T> 
{ 
    public T get1(T arg1); 

    public T get2(T arg1); 
} 

,并得到此异常:

不兼容的类型:INTF不是一个功能界面在界面中发现INTF 注 多个非压倒一切的抽象方法:有些邮件被简化了;与-Xdiags重新编译:冗长获得 全输出 1错误

是否有我不能使用lambda来代替匿名类的情况?

+1

_overcome_ it是什么意思?你明白错误吗? –

+0

1)功能接口只能有1个方法。 2)他们必须注释@FunctionalInterface –

+1

功能接口也被称为SAM类型(单一抽象方法类型)。所以,你的功能界面只能有一个抽象方法。 –

回答

15

不,没有办法“克服”这一点。功能接口只能有一个抽象方法。您的界面有两个:

interface Intf<T> { 
    public T get1(T arg1); 
    public T get2(T arg1); 
} 

注意:您不需要注释注释中提到的界面。但是如果您的接口不是有效的功能接口,则可以使用@FunctionalInterface注释来获得编译时错误。所以它为您的代码带来了更多的安全性。

欲了解更多信息,请参阅http://java.dzone.com/articles/introduction-functional-1

+1

感谢关于'@ FunctionalInterface'的提示!我忘记它有特殊的属性。另外,我发现从Oracle升级到最新的JDK8补丁也有助于改进错误消息。老版本的JDK8有时可能允许上面的代码进行编译,但在运行时会失败,并带有'java.lang.AbstractMethodError'。较新的版本将在编译时被拒绝。 – kevinarpe

1

想想看:

  • 应该如何编译器知道,如果你想覆盖get1get2

  • 如果您只覆盖get1,那么get2的实现是什么?即使你注释掉了,因为你没有实现get2将无法​​正常工作的代码...

是有原因的此限制...

0

如前所述通过@托马斯 - UHRIG,功能接口只能有一种方法

来解决这个问题,主要是因为你从来不使用public T get2(T arg1);的一种方式,是改变Intf<T>接口:

@FunctionalInterface 
interface Intf<T> 
{ 
    public T get1(T arg1); 
} 
6

仅供参考,以丰富已经给出了答案:

JSR-335: Lambda Expressions for the Java Programming Language在章节Lambda Specification,Part A:Functional Interfaces中说:

功能接口是一个接口ace只有一个摘要 方法(除了Object的方法),因此代表一个 单功能合同。 (在某些情况下,这种“单一”方法可能采用多个抽象方法的形式,具有从超接口继承的替代等效 签名;在这种情况下,继承的 方法在逻辑上代表单个方法。)

所以,你需要的是为你的一个方法提供一个默认的实现,或者把你的一个方法放在不同的接口中。