为什么我需要一个功能界面来处理lambdas?

cod*_*leb 33 java lambda java-8 functional-interface

我认为这个问题已经存在,但我无法找到它.

我不明白,为什么有必要使用功能界面来处理lambdas.请考虑以下示例:

public class Test {

    public static void main(String...args) {
        TestInterface i = () -> System.out.println("Hans");
//      i = (String a) -> System.out.println(a);

        i.hans();
//      i.hans("Hello");
    }
}

public interface TestInterface {
    public void hans();
//  public void hans(String a);
}
Run Code Online (Sandbox Code Playgroud)

这没有问题,但如果您取消注释注释行,它不会.为什么?在我的理解中,编译器应该能够区分这两种方法,因为它们具有不同的输入参数.为什么我需要一个功能界面并炸毁我的代码?

编辑:链接重复项没有回答我的问题,因为我问的是不同的方法参数.但是我在这里得到了一些非常有用的答案,感谢所有帮助过的人!:)

编辑2:对不起,我显然不是母语人士,但为了准确自己:

public interface TestInterface {
    public void hans();                 //has no input parameters</br>
    public void hans(String a);         //has 1 input parameter, type String</br>
    public void hans(String a, int b);  //has 2 input parameters, 1. type = String, 2. type = int</br>
    public void hans(int a, int b);     //has also 2 input parameters, but not the same and a different order than `hans(String a, int a);`, so you could distinguish both
}

public class Test {

    public static void main(String...args) {
        TestInterface i = () -> System.out.println("Hans");
        i = (String a) -> System.out.println(a);
        i = (String a, int b) -> System.out.println(a + b);
        i = (int a, int b) -> System.out.println(a);

        i.hans(2, 3);   //Which method would be called? Of course the one that would take 2 integer arguments. :)
    }
}
Run Code Online (Sandbox Code Playgroud)

我所要问的只是争论.方法名称无关紧要,但每个方法都采用不同参数的唯一顺序,因此,Oracle可以实现此功能,而不是仅根据"Lambda-Interface"使单个方法成为可能.

Era*_*ran 32

当你写:

TestInterface i = () -> System.out.println("Hans");
Run Code Online (Sandbox Code Playgroud)

你给出了一个实现void hans()方法TestInterface.

如果您可以将lambda表达式分配给具有多个抽象方法的接口(即非功能接口),则lambda表达式只能实现其中一个方法,而其他方法则不实现.

您无法通过将两个具有不同签名的lambda表达式分配给同一个变量来解决它(就像您不能将两个对象的引用分配给单个变量并期望该变量一次引用这两个对象).

  • @TrudleR:"如果你可以调用你实现了一个体的方法" - 你知道当你有一个任意接口实现的实例时,实现了哪些方法? (4认同)
  • TrudleR,你让我想到这里:) 但恕我直言,如果他们允许“只调用你实现了一个主体的方法”,他们会打开一个潘多拉盒子......:lambda 定义了 1 个方法,而你的接口是一个契约2; 背离这个契约真的会混淆你的对象的接收..另外,如果你的接口有几个带有 String 参数的方法,编译器将不知道哪一个与 lambda 表达式匹配。如果你想变得激进,你可以考虑 node.js,它根本不关心合同(=接口)...... (3认同)
  • @TrudleR,然后Java将是一种功能语言.如果您对JVM上的此类实现感兴趣.你可以尝试使用Scala语言. (2认同)
  • 您的问题的问题在于您强调了每个方法始终具有不同签名的事实。这只有在您坚持“一个 lambda 表达式与这些方法之一相关联”的想法时才有意义。如果您只是在考虑实现接口的紧凑方式,那么它不适用于 lambda 表达式的主要原因是,它们不应该是接口实现助手。→Lambda 表达式是*函数*。函数式接口只是在不改变类型系统的情况下将它们添加到 Java 的工具,而不是它们的目的。 (2认同)

bla*_*gae 21

他们必须只包含一种方法的最重要原因是,否则很容易产生混淆.如果接口中允许多个方法,如果参数列表相同,那么lambda选择哪个方法?

interface TestInterface {
    void first();
    void second(); // this is only distinguished from first() by method name
    String third(); // maybe you could say in this instance "well the return type is different"
    Object fourth(); // but a String is an Object, too !
}

void test() {
    // which method are you implementing, first or second ?
    TestInterface a = () -> System.out.println("Ido mein ado mein");
    // which method are you implementing, third or fourth ?
    TestInterface b = () -> "Ido mein ado mein";
}
Run Code Online (Sandbox Code Playgroud)


Dam*_*ash 8

您不必为了创建 lambda 函数而创建函数式接口。该接口允许您为将来的函数调用创建实例。

\n\n

在你的情况下,你可以使用已经存在的接口 Runable

\n\n

Runnable r = () -> System.out.println("Hans");

\n\n

然后打电话

\n\n

r.run();

\n\n

您可以将 lambda 视为->以下内容的简写:

\n\n
Runnable r = new Runnable() {\n     void run() {\n          System.out.println("Hans");`\n     }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用 lambda,您不需要匿名类,该类是在上面示例中创建的。

\n\n

但这有一些限制,为了弄清楚应该调用什么方法,与 lambda 一起使用的接口必须是 SAM(单一抽象方法)。那么我们就只有一种方法了。

\n\n

更详细的解释请阅读:

\n\n

函数式接口简介 \xe2\x80\x93 Java 8 中重新创建的概念

\n


use*_*751 5

你似乎在寻找匿名课程.以下代码有效:

public class Test {

    public static void main(String...args) {
        TestInterface i = new TestInterface() {
            public void hans() {
                System.out.println("Hans");
            }
            public void hans(String a) {
                System.out.println(a);
            }
        };

        i.hans();
        i.hans("Hello");
    }
}

public interface TestInterface {
    public void hans();
    public void hans(String a);
}
Run Code Online (Sandbox Code Playgroud)

Lambda表达式(大多数)是只用一种方法编写匿名类的较短方法.(同样,匿名类是您只在一个地方使用的内部类的简写)