什么是Lambda 表达式
// 不包含参数,用()表示没有参数
// 表达式主体只有一个语句,可以省略{}
Runnable helloWord = () -> System.out.println("Hello World");
// 表达式主体由多个语句组成,不能省略{}
Runnable helloWords = () -> {
System.out.println("Hello");
System.out.println("Word");
System.out.println("Word");
};
// 表达式中只有一个参数,可以省略()
Consumer<String> infoConsumer = msg -> System.out.println("Hello " + msg);
// 表达式由多个参数组成,不可省略()
BinaryOperator<Integer> add1 = (Integer i ,Integer j) -> i + j;
// 编译器会进行类型推断,在没有歧义情况下可以省略类型声明,但是不可省略()
BinaryOperator<Integer> add2 = (i, j) -> i + j;
综上可见,一个 Lambda 表达式主要由三部分组成:
- 参数列表
- 箭头分隔符(->)
- 主体,单个表达式或语句块
我们在使用匿名内部类时有一些限制:引用方法中的变量时,需要将变量声明为 final,不能为其进行重新赋值,如下:
final String msg = "World";
Runnable print = new Runnable() {
@Override
public void run() {
System.out.println("Hello" + msg);
}
};
在 Java8 中放松了这个限制,可以引用非 final 变量,但是该变量在既成事实上必须是 final 的,虽然无需将变量声明为 final,在 Lambda 表达式中,也无法用作非最终态变量,及只能给该变量赋值一次(与用 final 声明变量效果相同)。
Lambda之方法引用
Lambda 表达式一种常用方法便是直接调用其他方法,针对这种情况,Java8 提供了一个简写语法,及方法引用,用于重用已有方法。
凡是可以使用 Lambda 表达式的地方,都可以使用方法引用。
方法应用的标准语法为 ClassName::methodName,虽然这是一个方法,但不需要再后面加括号,因为这里并不直接调用该方法。
Function<User, String> f1 = user->user.getName();
Function<User, String> f2 = User::getName;
Supplier<User> s1 = ()->new User();
Supplier<User> s2 = User::new;
Function<Integer, User[]> sa1 = count -> new User[count];
Function<Integer, User[]> sa2 = User[]::new;
方法引用主要分为如下几种类型:
- 静态方法引用:className::methodName
- 实例方法引用:instanceName::methodName
- 超类实体方法引用:supper::mehtodName
- 构造函数方法引用:className::new
- 数组构造方法引用:ClassName[]::new
说白了Lambda 就是匿名内部类的简化写法