关于Java中的Lambda变量捕获

  • 博主简介:想进大厂的打工人
  • 博主主页: @xyk:
  • 所属专栏: JavaEE进阶

目录

一、Lambda表达式语法

二、Lambda中变量捕获


一、Lambda表达式语法

基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }

Lambda表达式由三部分组成:

  1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
  2. ->:可理解为"被用于"的意思
  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

二、Lambda中变量捕获

Java中,不通过Lambda函数入参传入的参数,我们称为函数的自由变量 ,在Lambda函数中使用自由变量的动作叫捕获

Lambda函数捕获的自由变量,必须是逻辑不变的(不可变或事实上无逻辑修改),通常用final修饰,通常理解为final修饰的变量或者实际final(没有被final修饰,但是使用前没有被修改,理解和被final修饰的变量是一样的)

Lambda函数只能捕获自由变量一次,这个变量的值,在多线程中为了防止发生线程安全问题,通常要把它设置为final或者实际final,例如:

可见,在变量捕获之前,没有进行任何修改,并且在多线程中不会发生线程安全问题,因为每次访问的都是同一个isQuit,那么如果改成方法内的局部变量会是什么样?如下:

可见,也是可以正常运行的,那么如果修改变量还能成功吗?请看:

如图,修改了变量,就不是实际final的变量了,因此lambda不能正确捕获。

那么如果我修改上面的静态成员变量,还可以捕获吗?如图:

答案是可以的,是没有报错的,这是因为如果多线程访问,都只是同一个isQuit变量,不会出现第二个isQuit变量;因为静态成员变量是分配在堆上的,堆上的数据是共享的,所以不会发生堆上变量在Lambda函数访问其之前被回收的问题;

但是如果是局部变量,多线程访问就会出现问题,因为变量在一个线程中被修改了,和其他线程的捕获结果也就不同了~~局部变量是在栈上分配的,可能会发生局部变量的分配逻辑和Lambda函数不在同一个线程的情况,若分配逻辑已经执行完,其栈上的变量将被回收,此时Lambda函数再去访问势必会出错。

相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读2 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang2 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
C语言小火车2 天前
C/C++ 为什么需要编译器?
开发语言·c++