lambda表达式,引用变量为什么为final
什么是lamda表达式
lambda表达式是java8提供的一种新特性,能进行简单的函数式编程,lambda表达式是一个匿名函数,可以把lambda表达式理解为一段可以传递的代码(将代码像数据一样进行传递),使得可以写出更简洁、更灵活的代码。
lamda表达式书写如下:
Runnable runnable1=()-> System.out.println("lambda表达式跑起来了");
list.stream().filter((e)->e.getAge()>18).forEach(System.out::println);
函数式接口的注解
@FunctionalInterface
lambda表达式的本质
lambda表达式本质是解决匿名内部类的问题,如下面的等价转化
匿名内部类
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类跑起来了");
}
};
lambda表达式
Runnable runnable1=()-> System.out.println("lambda表达式跑起来了");
上面2个是等价的,lambda表达式就是为了替代匿名内部类
为什么引用的变量是final
上面说到,lambda表达式是替代匿名内部类,并且可以理解为一段可以传递的代码。那我们在引用局部变量时,为啥是要修饰final。
- lambda表达式的内容可用传递到其他线程去执行,这样会导致局部变量的问题,如果局部变量的方法执行完,局部变量就消失了,你再另外的线程修改局部变量的值,当然就出现错误了。
- 在堆栈的角度,lambda表达式他是匿名内部类,类存在于堆中,而方法的局部变量是存在于虚拟机栈中,方法执行完,栈帧就出栈了,局部变量也就不存在了,而堆中的lambda表达式仍可存在,如果此时修改局部变量,就会出错
所以,lambda表达式引用的变量要为不可变,即用final修饰,传入的变量会生成一个不可变的副本,也避免并发问题,在java8后可以不用final修饰,但是实质上也是个final的变量,修改就会报错。
Stream
lambda表达式的好伙伴Stream,是java8的新特性,用于算法和计算,更像一个高级的迭代Iterator,对于元素集合统一、快速、并行操作的一种方式,充分利用多核优势,配合lambda表达式、链式结构对集合进行许多有用的操作,示例如下:
List adultList= persons.stream()
.filter(p -> p.getAge() > 18)
.map(person -> new Adult(person))
.collect(Collectors.toList());
int countOfAdult=persons.stream()
.filter(p -> p.getAge() > 18)
.map(person -> new Adult(person))
.count();
总结
lambda表达式让我们方便点的进行函数式编程,减少了代码量,也美化了代码,让我们继续使用lambda表达式吧。