Lambda表达式介绍
Lambda表达式是在java规范提案JSR 335中定义的,Java 8 中引入了Lambda表达式,并被认为是Java 8最大的新特性,Lambda表达式促进了函数式编程,简化了Java编程开发。
背景知识
匿名内部类
在Java中,匿名内部类一般适用于那些在Java应用中只会出现一次的实现类,举个例子,在标准的Swing或JavaFX应用中,有很多键盘和鼠标的事件处理程序,一般情况下,你不需要写一个单独的事件处理类,而是使用如下方式(有Swing编程经验的应该很熟悉吧):
JButton testButton = new JButton("Test Button"); testButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.out.println("Click Detected by Anon Class"); } });
不这样做的话,你需要针对每一个事件写一个单独的ActionListener接口的实现类,这样的代码并不优雅,因为仅仅为了定义一个方法就需要附加写一大堆的代码。通常,哪里需要,就在哪里创建对应的匿名内部类,这样的代码可读性会更强。
Functional Interfaces函数式接口
首选,我们来观察下上面提到的ActionListener接口的定义,如下:
package java.awt.event; import java.util.EventListener; public interface ActionListener extends EventListener { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e); }
在上面的代码中,只定义了一个方法,在Java 8中,像这样的接口被称为“functional interface”。通常在Java中,我们经常使用匿名内部类来实现函数式接口,这是一种很常见的使用模式;
另外,在JDK中,除了ActionListener接口外,类似的还有Runnable和Comparator接口。
Lambda表达式语法
Lambda表达式的语法形式如下:
parameter -> expression body
主要组成:参数列表 + 箭头 + 表达式体,如 (int x, int y) -> x + y
其中,表达式体可以是一条表达式,也可以是一个语句块(多条代码语句);
Lambda表达式具有如下特征:
- 【可选】类型声明:参数的类型不需要声明,编译器可以根据参数值推断出其类型;
- 【可选】括号:单个参数的话,不需要用圆括号包围参数,当然,对于多个参数或无参数的话,括号是需要的;
- 【可选】花括号:如果表达式主体只有一条语句的话,不需要用花括号包围,当然,对于多条语句,花括号是需要的;
- 【可选】return关键字:如果表达式主体是单一表达式,return关键字可以不写,编译器可以自动返回该值,当然,如果写了return,则需要加上花括号;
举个例子:
package lambda; /** * LambdaTest * * @author Pi Chen * @version V1.0.0, 2016年9月19日 * @see * @since V1.0.0 */ public class LambdaTest { public static void main(String args[]) { LambdaTest tester = new LambdaTest(); // 有参数类型 MathOperation addition = (int a, int b) -> a + b; // 无参数类型 MathOperation subtraction = (a, b) -> a - b; // 有花括号,有return关键字 MathOperation multiplication = (int a, int b) -> { return a * b; }; // 无花括号,无return关键字,单一表达式情况 MathOperation division = (int a, int b) -> a / b; // MathOperation调用示例 System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 有括号 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 无括号,单个参数情况 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); // GreetingService调用示例 greetService1.sayMessage("Mahesh"); greetService2.sayMessage("Suresh"); //有括号, 无参情况 Runnable runTest = () -> System.out.println("Running"); //Runnable调用示例 runTest.run(); } // 内部接口 interface MathOperation { int operation(int a, int b); } interface GreetingService { void sayMessage(String message); } interface Runnable { void run(); } private int operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); } }
关键点说明:
- Lambda表达式主要用于定义一个函数式接口(functional interface:一个只包含一个方法的接口)的内联实现,在上面的例子中,我们使用了各种类型的Lambda表达式来实现MathOperation接口的operation方法,接着又实现了GreetingService接口的sayMessage方法,Runnable接口的run方法;
- Lambda表达式消除了匿名类的使用并且赋予Java简单且强大的函数式编程能力;
参考资料
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html#overview
https://www.tutorialspoint.com/java8/java8_lambda_expressions.htm