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

相关推荐
架构师沉默4 小时前
设计多租户 SaaS 系统,如何做到数据隔离 & 资源配额?
java·后端·架构
Java中文社群5 小时前
重要:Java25正式发布(长期支持版)!
java·后端·面试
每天进步一点_JL6 小时前
JVM 类加载:双亲委派机制
java·后端
用户298698530147 小时前
Java HTML 转 Word 完整指南
java·后端
渣哥7 小时前
原来公平锁和非公平锁差别这么大
java
渣哥7 小时前
99% 的人没搞懂:Semaphore 到底是干啥的?
java
J2K7 小时前
JDK都25了,你还没用过ZGC?那真得补补课了
java·jvm·后端
kfyty7257 小时前
不依赖第三方,不销毁重建,loveqq 框架如何原生实现动态线程池?
java·架构
isysc19 小时前
面了一个校招生,竟然说我是老古董
java·后端·面试
道可到12 小时前
Java 反射现代实践速查表(JDK 11+/17+)
java