Java8 教程

Java8 Lambda 表达式语法

要正确、熟练运用 Lambda 表达式,我们需要先正确了解 Lambda 表达式的语法。

Lambda 表达式语法

Lambda 表达式的语法如下:

(parameters) -> expression

或者

(parameters) -> { statements; }

说明:

  • parameters: 参数列表,可以是空的,或者包含一个或多个参数。

  • ->(箭头符号): 表示 Lambda 表达式的开始,后面可以跟一个表达式或者一段代码块。如果是表达式,那么该表达式的值将作为 Lambda 函数的返回值;如果是代码块,那么代码块中的语句将会被执行,并且需要使用 return 语句显式返回一个值。

  • expression:一个表达式,该表达式的值将作为 Lambda 表达式的返回值。

  • statements:一个代码块,需要使用大括号括起来,并且通过 return 语句返回值。

Lambda 表达式示例

下面通过几个示例分别介绍 Lambda 表达式基本形式以及几种变种。

没有无参

Lambda 表达式可以不指定任何参数,如下:

Runnable noArguments = () -> System.out.println("Hello World");

上述 Lambda 表达式不包含参数,使用空括号 () 表示没有参数。并且它实现了 Runnable 接口,该接口只有一个 run() 方法,没有参数,返回类型为 void。

只有一个参数

Lambda 表达式可以指定一个参数,参数可以通过括号括起来,如下:

ActionListener oneArgument = event -> System.out.println("button clicked");
// 或者
ActionListener oneArgument = (event) -> System.out.println("button clicked");

上述 Lambda 表达式仅仅包含了一个参数 event。如果仅有一个参数,可以省略括号。

代码块

Lambda 表达式的主体部分允许指定多条语句,多条语句需要使用大括号 {} 括起来,如下:

Runnable multiStatment = () -> {
   System.out.println("Hello");
   System.out.println(" World");    
};

Lambda 表达式的主体不仅可以是一个表达式,而且也可以是一段代码块,代码块需要使用大括号将代码括起来。

多参数

Lambda 表达式支持传递多个参数,如下:

BinaryOperator<Long> add = (x, y) -> x + y;
// 或者
BinaryOperator<Long> add = (Long x, Long y) -> x + y;

Lambda 表达式也可以表示包含多个参数的方法。上面代码中,并不是将 x 和 y 数字相加,而是创建了一个函数,用来计算 x 和 y 数字相加的结果。变量 add 的类型是 BinaryOperator<Long>,它不是x 和 y 两个数字的和,而是将 x 和 y 两个数字相加的那行代码。

注意:在 Lambda 表达式中,只在某些分支中返回值(其他分支没有返回值)是不合法的,例如:

// 不合法
(int x) -> { if(x >= 0) return 1; }

// 合法
(int x) -> {
   if(x >= 0) {
       return 1;    
   }
   return 0;
}

Lambda 类型推断

目标类型是指 Lambda 表达式所在上下文环境的类型。比如,将 Lambda 表达式赋值给一个局部变量,或传递给一个方法作为参数,局部变量或方法参数的类型就是 Lambda 表达式的目标类型。

Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。例如:

Runnable task = () -> System.out.println("Hello World");

上述代码,编译器可以轻易推断出 Lambda 表达式的目标类型是 Runnable。

目标类型也不是一个全新的概念,Java 中初始化数组时,数组的类型就是根据上下文推断出来的,例如:

String[] array = {"hello", "world"};

在 Java 8 之前,在进行匿名接口实现时,您必须指定要实现的接口。下面是本文开头的匿名接口实现示例:

stateOwner.addStateListener(new StateChangeListener() {

    public void onStateChange(State oldState, State newState) {
        // do something with the old and new state.
    }
    
});

使用 lambda 表达式时,通常可以从周围的代码中推断出类型。例如,可以从 addStateListener() 方法(StateChangeListener 接口上的单个方法)的方法声明中推断出参数的接口类型。这就是所谓的类型推断。编译器通过在其他地方查找参数的类型 —— 在本例中就是方法定义 —— 来推断参数的类型。下面是本文开头的示例,显示了 lambda 表达式中没有提到 StateChangeListener 接口:

stateOwner.addStateListener(
    (oldState, newState) -> System.out.println("State changed")
);

在 lambda 表达式中,参数类型通常也可以推断出来。在上例中,编译器可以从 onStateChange() 方法的声明中推断出参数的类型。因此,参数 oldState 和 newState 的类型是从 onStateChange() 方法的方法声明中推断出来的。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号