Lambda表达式的本质只是一个语法糖,由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。
1.
lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = str -> str.length();
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);
}
}
interface Processor {
int getStringLength(String str);
}
输出:11
2.
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
String text = "test";
List list = Arrays.asList(1,2);
list.forEach(value -> {
System.out.println(text + value);
});
输出:
test1
test2
String text = "test";
text="test change";
List list = Arrays.asList(1,2);
list.forEach(value -> {
System.out.println(text + value);
});
//报错: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量
String first = "";
Comparator comparator = (first, second) -> Integer.compare(first.length(), second.length());
//编译出错:已在方法 main(java.lang.String[])中定义了变量 first
3.
方法引用:若Lambda体中的内容有方法已经实现了,那么我们可以使用"方法引用"
主要有三种语法格式:
- 对象::实例方法名
- 类::静态方法名
- 类::实例方法名
注意:
-
- Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保存一致
-
- 若Lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
//1.对象::实例方法名
Employee emp = new Employee(101, "lily", 18);
Supplier sup = () -> emp.getName();
System.out.println(sup.get());
System.out.println("----------------------------------");
Supplier sup2 = emp::getName;
System.out.println(sup2.get());
//2.类::静态方法名
Arrays.asList("We will build a great wall and Mexico will pay."
.split(" "))
.forEach(MyLogger::log); //log(..)就是MyLogger类中的静态方法
//3.类::实例方法名
BiPredicate bp = (x, y) -> x.equals(y);
System.out.println(bp.test("abcde", "abcde"));
System.out.println("-----------------------------------------");
//前提:第一个参数是实例方法的调用者,第二个参数是实例方法的参数
//例如 x 是equals方法的调用者,y是实例方法的参数
BiPredicate bp2 = String::equals;
System.out.println(bp2.test("abc", "abc"));
构造器引用 :
ClassName::new
构造器的参数列表,需要与函数式接口中参数列表保持一致
Supplier sup = ()-> new Employee();
Employee emp = sup.get();
//构造器引用
//根据参数列表自动匹配构造器
Supplier sup2 = Employee::new;
emp = sup2.get();
System.out.println(emp);