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

相关推荐
一只小青团3 小时前
Python之面向对象和类
java·开发语言
qq_529835353 小时前
ThreadLocal内存泄漏 强引用vs弱引用
java·开发语言·jvm
景彡先生3 小时前
C++并行计算:OpenMP与MPI全解析
开发语言·c++
落笔画忧愁e3 小时前
扣子Coze飞书多维表插件添加数据记录
java·服务器·飞书
量子联盟5 小时前
原创-基于 PHP 和 MySQL 的证书管理系统,免费开源
开发语言·mysql·php
秋千码途6 小时前
小架构step系列08:logback.xml的配置
xml·java·logback
飞翔的佩奇6 小时前
Java项目:基于SSM框架实现的旅游协会管理系统【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·mysql·毕业设计·ssm·旅游·jsp
时来天地皆同力.6 小时前
Java面试基础:概念
java·开发语言·jvm
hackchen6 小时前
Go与JS无缝协作:Goja引擎实战之错误处理最佳实践
开发语言·javascript·golang
找不到、了6 小时前
Spring的Bean原型模式下的使用
java·spring·原型模式