• 1.1简介

Java 8 是 Java 语言发展史上的一个重要里程碑,更新了许多新特性,包括 Lambda、流和函数式编程等等。这些特性可以使代码更简洁、易阅读、易维护。Java 程序员必须掌握这些新特性,必须与时俱进,不能 out 哦。

  1. fruits.forEach(f -> {
  2. System.out.println(f.getName());
  3. });

f -> {},这就是 Lambda 表达式。

1.2无参数类型

Lambda表达式的基本结构为:f -> {}

f 变量的类型是什么呢?答案是:类型是系统根据上下文 自动 识别的。<br />
Lambda 表达式 {} 内的执行语句,除了能引用参数变量以外,还可以引用外部的变量

因为使用 Lambda 表达式有规范:引用的 局部变量 不允许被修改
我们在《Java面向对象》课程中写过 final 关键字,Lambda 表达式引用的 局部变量 即使不声明为 final,也要具备 final 的特性:变量值初始化后不允许被修改

使用 Lambda 表达式还有一点需要注意:参数不能与 局部变量 同名。下列写法是错误的

  1. String f = "水果名称:";
  2. fruits.forEach(f -> {});

Java 8 支持了一种新的语法:双冒号 “::”,这也是一种 Lambda 写法 ,是与 Lambda 表达式相关的一个重要特性。

  1. names.forEach(System.out::println);

这段代码的重点是使用 :: 时,系统每次遍历取得的元素(n),会 自动 作为参数传递给 System.out.println() 方法打印输出:
System.out::println 等同于 n -> {System.out.println(n);}
:: 语法干脆省略了参数变量,所以读这段代码需要相互对照、并且自行脑补
**
Lambda表达式 - 图1

用法一:静态方法调用

用法二:非静态方法调用

print() 方法不再标识为 static,于是需要实例对象来调用。

  1. fruits.forEach(new LambdaTest()::print);

只是简写了:

  1. LambdaTest lt = new LambdaTest();
  2. fruits.forEach(lt::print);

效果是一样的。
实际上,本节开头的案例中,System.out::println 语句就是调用非静态方法 println(),因为 System.out 指代的是一个实例对象。只是这个实例对象比较复杂,不是本课程重点

方法三:多参数

  1. Collections.sort(students, (student1, student2) -> {
  2. // 第一个参数的学号 vs 第二个参数的学号
  3. return student1.getRollNo() - student2.getRollNo();
  4. });

就碰到了多参数的情况。如果把比较的过程定义成一个方法:

  1. private static int compute(Student s1, Student s2) {//所在类为 SortTest.java
  2. return student1.getRollNo() - student2.getRollNo();
  3. }

那么排序的过程可以简化为:

  1. Collections.sort(students, SortTest::compute);

注意,系统会 自动 获取上下文的参数,并按上下文定义的 顺序 传递给指定的方法。所谓 顺序 就是 Lambda 表达式 () 中的顺序。

方法四:父类方法

我们在《Java面向对象》学过,super 关键字的作用是在子类中引用父类的属性或者方法。那么同样,:: 语法也可以用 super 关键字调用父类的非静态方法。