带有Lambda表达式的以下代码如何编译?

时间:2019-05-05 18:10:16

标签: java lambda

我正在阅读Herbert Shildt的书-Java的Lambda示例的完整参考。该代码写在LambdasAsArgumentsDemo.java文件的侧面

interface StringFunc {
String func(String n);
}

class LambdasAsArgumentsDemo {

public static void main(String args[]){
    String inStr = "Lambdas add power to Java";
    String outStr;
    // Here, a simple expression lambda that uppercases a string is passed to stringOp( ).
    outStr = stringOp((str) -> str.toUpperCase(), inStr);
    System.out.println("The string in uppercase: " + outStr);

//This method has a functional interface as the type of its
// first parameter. Thus, it can be passed a reference to
//any instance of that interface, including the instance 
//created by a lambda expression.
//The second parameter specifies the string to operate on.

        static String stringOp(StringFunc sf, String s) {
            return sf.func(s);
        }
    }

现在我的问题已经解决

outStr = stringOp((str) -> str.toUpperCase(), inStr);

当您将(str) -> str.toUpperCase()作为参数传递时,确实会创建功能接口StringFunc的实例,并且对该对象的引用作为参数传递。 stringOp()的第一个参数?如何知道实例化StringFunc

1 个答案:

答案 0 :(得分:3)

StringFunc定义了一个函数的接口,该函数将字符串作为参数并返回一个字符串。您的lambda表达式(str) -> str.toUpperCase()的作用相同。它需要一个字符串((str)并返回一个字符串(str.toUppercase()),因此它与接口匹配。

这样想:无需实例化该接口的对象,因为lambda已经是实例。将其强制转换为接口就足够了。 str将成为参数的名称。

您可以通过使用带有该签名的常规方法来获得相同的结果:

public static void main(String args[]){
    String inStr = "Lambdas add power to Java";
    String outStr;
    outStr = stringOp(LambdasAsArgumentsDemo::mymethod, inStr);
    System.out.println("The string in uppercase: " + outStr);
}

public static String mymethod(String str) { return str.toUpperCase(); }
              ^                 ^                  ^
              |                 |                  implementation
              |                 String argument called str
              String return type

从评论中:

  

顺便说一句,我还有其他相关问题。如果有两个类似的其他功能接口,例如接口StringFunc2 {String func2(String n); }和接口StringFunc3 {字符串func3(int n);在这种情况下,它将如何解决?有什么解释?顺便说一句,它仍然可以编译并产生相同的输出。

代码调用stringOp()stringOp()使用StringFuncStringFunc2StringFunc3。因此,编译器会在编译时知道要选择哪一个。

但是,如果您定义了三个接口和三个函数,则该代码将无法编译,并会失败并显示一条错误消息,提示调用不明确,因为lambda可能是其中之一。

import java.util.*;
import java.lang.*;
import java.io.*;

interface StringFunc {
    String func(String n);
}
interface StringFunc2 {
    String func(String n);
}
interface StringFunc3 {
    String func(String n);
}

class LambdasAsArgumentsDemo {

    public static void main(String args[]){
        String inStr = "Lambdas add power to Java";
        String outStr;
        outStr = stringOp((str) -> str.toUpperCase(), inStr);
        System.out.println("The string in uppercase: " + outStr);
    }

    static String stringOp(StringFunc sf, String s) {
        return sf.func(s);
    }

    static String stringOp(StringFunc2 sf, String s) {
        return sf.func(s)+"2";
    }

    static String stringOp(StringFunc3 sf, String s) {
        return sf.func(s)+"3";
    }
}