20

我这样做了:

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:verbose 重新编译以获得完整的输出 1 错误

有什么条件不能使用 lambda 替换匿名类吗?

4

4 回答 4

26

不,没有办法“克服”这一点。一个函数式接口必须只有一个抽象方法。您的界面有两个:

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

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

有关更多信息,请参见http://java.dzone.com/articles/introduction-functional-1

于 2014-05-15T15:16:24.073 回答
8

仅供参考并丰富已经给出的答案:

根据JSR-335: Lambda Expressions for the Java Programming Language,在 Lambda Specification, Part A: Functional Interfaces 部分中它说:

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

因此,您需要为您的方法之一提供默认实现,或者将您的方法之一放在不同的接口中。

于 2014-05-15T15:23:36.537 回答
3

想一想:

  • 编译器应该如何知道您是否要覆盖get1or get2

  • 如果你只覆盖get1,那将是什么get2实现?即使您注释掉的代码也不起作用,因为您没有实现get2......

这种限制是有原因的......

于 2014-05-15T15:18:47.410 回答
1

正如@Thomas-Uhrig 所说,功能接口只能有一种方法

解决此问题的一种方法(主要是因为您从不使用public T get2(T arg1);)是将Intf<T>界面更改为:

@FunctionalInterface
interface Intf<T>
{
    public T get1(T arg1);
}
于 2014-05-15T15:19:48.380 回答