编写你的第一个 Lambda 函数
学习如何编写你的第一个lambda表达式。
什么是 lambda 表达式?
Java 是一种面向对象的语言。在 Java 8 中引入 lambda 表达式,其目的是让 Java 融入函数式编程的特性。你可能会好奇,面向对象编程和函数式编程之间有什么区别?
在 面向对象编程 中,对象和类是核心实体。如果我们创建一个函数,它必须存在于某个类内部。函数在类对象的范围之外是没有意义的。
在 函数式编程 中,函数可以独立于对象存在。我们可以将函数赋给变量,也可以将其作为参数传递给其他方法。
lambda 表达式 就是一个匿名函数,即没有名称且未绑定到标识符的函数。我们可以将其作为参数传递给其他方法,从而在 Java 中利用函数式编程的强大能力。
如何编写 lambda 表达式
理解 lambda 的概念以及如何编写 lambda 可能会比较困难,如果不看示例的话。因此,我们先来看一个例子,然后再回顾之前的内容。
在下面的例子中,我们有一个名为 Greeting 的函数式接口。有两个类 HindiGreeting 和 EnglishGreeting 实现了这个接口。
1@FunctionalInterface 2public interface Greeting { 3 void greet(); 4}
1public class HindiGreeting implements Greeting { 2 3 // 重写 Greeting 接口中的 greet() 方法。 4 @Override 5 public void greet() { 6 System.out.println("Namaste"); 7 } 8}
1public class EnglishGreeting implements Greeting { 2 3 // 重写 Greeting 接口中的 greet() 方法。 4 @Override 5 public void greet() { 6 System.out.println("Good Morning"); 7 } 8}
还有一个名为 WellWisher 的类。该类有一个名为 wish(Greeting greeting) 的方法,它接收一个 Greeting 类型的参数,并根据传入的对象类型打印相应的问候语。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 public static void main(String args[]) { 8 Greeting hindiGreeting = new HindiGreeting(); 9 wish(hindiGreeting); // 传入 HindiGreeting 对象。 10 11 Greeting englishGreeting = new EnglishGreeting(); 12 wish(englishGreeting); // 传入 EnglishGreeting 对象。 13 } 14}
当我们运行 WellWisher 类时,输出如下:
1Namaste 2Good Morning
这是一个典型的面向对象编程示例。现在,如果我们希望 WellWisher 类能够用所有可用的语言进行问候,该怎么办?
是否需要为每种语言都创建一个类,比如 SpanishGreeting、FrenchGreeting 等?
难道不能不创建任何类,直接把一个函数传给 wish(Greeting greeting) 方法吗?
我们的 wish(Greeting greeting) 方法可以直接执行传入的函数并打印问候语。
这可以通过匿名类实现。我们快速看一下如何使用匿名类来完成,然后直接进入 lambda 表达式。
在下面的例子中,我们将修改 WellWisher 类以使用匿名类。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 public static void main(String args[]) { 8 // 我们将一个匿名类对象传给 wish 方法。 9 wish(new Greeting() { 10 @Override 11 public void greet() { 12 System.out.println("Namaste"); 13 } 14 }); 15 } 16}
在上面的例子中,我们不需要为每种语言创建一个类。通过使用匿名类,我们就能实现所需的功能。但你有没有觉得这段代码仍然显得繁琐?尽管类是匿名的,但我们依然在创建一个类。
为了使代码更简洁,我们逐步移除不必要的部分,最终写出第一个 lambda 表达式。
步骤 1 -> 编译器知道 wish(Greeting greeting) 方法接收的是 Greeting 类型的参数。因此,我们不需要显式地创建一个 Greeting 类型的匿名类。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 public static void main(String args[]) { 8 wish( 9 public void greet() { 10 System.out.println("Namaste"); 11 } 12 ); 13 } 14}
步骤 2 -> 我们知道 Greeting 接口只有一个方法。因此,我们不需要写出方法名,只关心方法体即可。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 public static void main(String args[]) { 8 wish( 9 public void () { 10 System.out.println("Namaste"); 11 } 12 ); 13 } 14}
步骤 3 -> 编译器可以推断出该方法体不返回任何值。因此,声明返回类型是多余的,同时也可以去掉 public 修饰符。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 public static void main(String args[]) { 8 wish( 9 () -> { 10 System.out.println("Namaste"); 11 } 12 ); 13 } 14}
请注意,在空括号和方法体之间添加了
->。这就是定义 lambda 表达式的方式。
我们还可以进一步优化。由于方法体只包含一行代码,花括号也是多余的。
1public class WellWisher { 2 3 public static void wish(Greeting greeting) { 4 greeting.greet(); 5 } 6 7 // 将 lambda 表达式传给 wish 方法。 8 public static void main(String args[]) { 9 wish( () -> System.out.println("Namaste") ); 10 } 11}
恭喜!你已经写出了你的第一个 lambda 表达式。编写 lambda 表达式其实非常简单。
总结一下,当我们编写 lambda 表达式时,本质上是在将一个函数作为方法参数传递,并且它会被直接执行。
Quiz
关于 lambda 表达式,以下哪些说法是正确的?