JAVA 8 Lambda表达式-Lambda Expressions

时间:2021-08-04 18:50:31

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