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

相关推荐
程序员-Benothing18 小时前
如何实现高并发系统订单30分钟自动关闭?
开发语言·c#·wpf
郝学胜-神的一滴19 小时前
Python 高级编程 026:内置数据结构之骈文纵论
开发语言·数据结构·python·程序人生·软件工程
隐积1 天前
3.1.7.Qt容器大家族(3):QVariant——万能盒子
开发语言·qt
都叫我大帅哥1 天前
Java JJWT 完全指南:从入门到生产级实践
java
名字还没想好☜1 天前
Next.js ‘use client‘ 到底加在哪:Server/Client Components 边界与常见报错
开发语言·前端·javascript·react·next.js
初级代码游戏1 天前
iOS开发 Swift 速记1:变量和基本数据类型
开发语言·ios·swift
前端开发张小七1 天前
Java 学习笔记 · 第一课:基础语法与核心概念
java·后端
酷在前行1 天前
【R生态】PERMANOVA 进阶实战:距离选择、PERMDISP、两两比较与受限置换(保姆级教程)
开发语言·r语言
ThsPool1 天前
【ENVI二次开发学习整理 04】ENVI功能扩展与二次开发
java·前端·javascript
cxr8281 天前
Graphify vs GitNexus vs CodeGraph — 三工具架构深度对比
开发语言·架构·知识图谱