一、Lambda表达式简介
lambda表达式本质上就是一个匿名(即未命名)的方法,但是,这个方法不是独立运行的,而是用于实现由函数式接口定义的另外一个方法。因此,lambda表达式会导致产生一个匿名类,lambda表达式也常被称为闭包。
lambda表达式的操作符是->,它将lambda表达式分成两个部分,左侧指定了lambda表达式所需要的参数,右侧指定了lambda体。
1:举例
@FunctionalInterface
public interface MyNumber {
double getValue();
}
MyNumber value = () -> 1.2;
System.out.println(value.getValue());
lambda表达式也可以指定参数:
@FunctionalInterface
public interface MyNumber {
boolean iseven(int n);
}
MyNumber value = (n) -> n%2 == 0;
System.out.println(value.iseven(3));
总结:lambda表达式不是独立执行的,而是构成了一个函数式接口定义的抽象方法的实现,该抽象方法定义了lambda表达式的目标类型。结果:只有在定义了lambda表达式的目标类型上下文中(也就是函数式接口),才能使用该表达式。当把lambda表达式赋给一个函数式接口的引用时,就创建了这样的上下文。
当目标类型上下文中出现lambda表达式时,会自动创建实现了函数式接口的一个类的实例,函数式接口声明的抽象方法的行为由lambda表达式定义。如(n) -> n%2 == 0时,会创建实现了MyNumber接口的一个类的实例,这个类实现了boolean iseven(int n)方法。因此,lambda表达式提供了一种将代码片段转换为对象的方法。
为了在目标类型上下文中使用lambda表达式,抽象方法的类型和lambda表达式的类型必须能够兼容。例如:如果抽象方法定义了两个int类型的参数,那么lambda表达式也必须指定两个参数,其类型要么被显示指定为int类型,要么在上下文中可以被隐式地推断出为int类型。总的来说,lambda表达式的参数类型和参数数量必须与方法的参数兼容、返回类型必须兼容、并且lambda表达式可能抛出的异常必须能被方法接受。
关键点:MyNumber value = (n) -> n%2 == 0
这句话背后的内容是:a class instance is constructed in which the lambda expression implements the boolean iseven(int n)
method in MyNumber。
二、Lambda表达式的一个重要特点
函数式接口引用可以用来执行任何与其兼容的lambda表达式。
public static void main(String[] args) throws Exception{
Runnable runnable = () -> {
int a = 1;
System.out.println(Thread.currentThread().getName()+""+a);
};
Runnable runnable2 = () -> {
String s = "name";
System.out.println(Thread.currentThread().getName()+""+s);
};
runnable.run();
runnable2.run();
}
在程序中定义了两个不同的lambda表达式,他们都与函数式接口Runnable的run()方法兼容,第一个是输出int,第二个是输出String,因为每个表达式都与run()兼容,所以都可以通过Runnable的引用来执行。