关于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函数再去访问势必会出错。

相关推荐
AC赳赳老秦几秒前
OpenClaw + 飞书多维表格:自动同步数据、生成统计图表、触发自动化任务
java·大数据·python·缓存·自动化·deepseek·openclaw
geovindu6 分钟前
python: Reactor Pattern
开发语言·python·设计模式·反应器模式
CS_SKILL11 分钟前
吉比特 C++ 实习一面面经:一轮把 C++、容器、并发、排序和网络全扫了一遍
java·开发语言·校招面经·实习面经·技术面经·吉比特校招
feifeigo12313 分钟前
基于多混沌映射的图像加密(MATLAB实现)
开发语言·matlab
techdashen16 分钟前
Go 语言仓库 Top 100 贡献者分析报告
开发语言·后端·golang
何以解忧,唯有..16 分钟前
Go 语言变量命名规范详解
开发语言·后端·golang
专注搞钱20 分钟前
Python自动爬设备报警日志,每天省1小时
开发语言·python·半导体
三品吉他手会点灯29 分钟前
C语言学习笔记 - 48.流程控制2 - 什么是流程控制
c语言·开发语言·笔记·学习
Jul1en_29 分钟前
【SpringCloud】SkyWalking 链路追踪知识详解及部署教程
java·后端·spring·spring cloud·skywalking
宸津-代码粉碎机30 分钟前
Spring AI 企业级实战|智能记忆摘要+自动遗忘机制落地,彻底解决上下文爆炸与Token冗余
java·大数据·人工智能·后端·python·spring·云计算