Lambda 表达式的作用域
在Lambda表达式中访问外层作用域和旧版本的匿名对象中的方式类似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
Lambda表达式不会从超类(supertype)中继承任何变量名,也不会引入一个新的作用域。Lambda表达式基于词法作用域,也就是说lambda表达式函数体里面的变量和它外部环境的变量具有相同的语义(也包括lambda表达式的形式参数)。此外,this关键字及其引用,在Lambda表达式内部和外部也拥有相同的语义。
1.访问局部变量
1)可以直接在lambda表达式中访问外层的局部变量
eg:
final int num = 1;
Converter<Integer, String> s =(param) -> String.valueOf(param + num);s.convert(2); // 3
但是和匿名对象不同的是,lambda表达式的局部变量(eg:num)可以不用声明为final
eg:
int num = 1;
Converter<Integer, String> s =(param) -> String.valueOf(param + num);stringConverter.convert(2); // 3
不过这里的局部变量(eg:num)必须不可被后面的代码修改(即隐性的具有final的语义)
eg:下面代码无法编译
int num = 1;
Converter<Integer, String> s =(param) -> String.valueOf(param + num);
num = 5;
Note:在Lambda表达式中试图修改局部变量是不允许的。
2)在 Lambda 表达式当中被引用的变量的值不可以被更改。
public void repeat(String string, int count) {Runnable runnable = () -> {for (int i = 0; i < count; i++) {string = string + "a";//编译出错System.out.println(this.toString());}};new Thread(runnable).start();
}
3)在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
eg:
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(),//编译会出错second.length());
2.访问对象字段与静态变量
和局部变量不同的是,Lambda内部对于实例的字段(即:成员变量)以及静态变量是即可读又可写。
eg:
class LambdaDemo {static int myStaticNum;int myNum;void testScopes() {Converter<Integer, String> s1 = (param) -> {myNum = 33;return String.valueOf(param);};Converter<Integer, String> s2 = (param) -> {myStaticNum = 87;return String.valueOf(param);};}
}
3.不能访问接口的默认方法
Lambda表达式中是无法访问到默认方法的。
4.Lambda表达式中的this
Lambda 表达式中使用 this 会引用创建该 Lambda 表达式的方法的 this 参数。
eg:
public class Test2 {public static void main(String[] args) {Test2 test = new Test2();test.method();}@Overridepublic String toString() {return "Lambda";}public void method() {Runnable runnable = () -> {System.out.println(this.toString());};new Thread(runnable).start();}
}
显示结果:Lambda
5.综合理解Lambda表达式的作用域
(注:如果上面的3条内容都理解了,就不用再仔细看下面这个示例和分析了。)
eg:
public class Test {public static void main(String[] args) {repeatMessage("Hello world", 20);}public static void repeatMessage(String text,int count){Runnable r = () -> {for(int i = 0; i < count; i++){System.out.println(text);Thread.yield();}};new Thread(r).start();}
}
分析: Lambda表达式中的变量count和text,它们并没有在Lambda表达式中被定义,而是方法的参数。Lambda表达式可能会在repeatMessage()返回之后才运行,此时参数变量已经消失了。如果保留text和count变量会怎样呢?
为了更好地理解上面的情况,我们需要对Lambda表达式有更深入的理解。
一个lambda表达式包括三个部分:
一段代码。
参数。
自由变量的值,这里的“自由”指的是那些不是参数并且没有在代码中定义的变量。
在示例中,lambda表达式有两个自由变量,text和count。数据结构表示Lambda表达式必须存储这两个变量的值,即“Hello world ”和20。可以理解为,这些值已经被Lambda表达式捕获了(这是一个技术实现的细节。eg:你可以将一个lambda表达式转换为一个只含一个方法的对象,这样自由变量的值就会被复制到该对象的实例变量中)。
Note:含有自由变量的代码块才被称之为“闭包(closure)”。在Java中,lambda表达式就是闭包。事实上,内部类一直都是闭包。Java8中为闭包赋予了更吸引人的语法。
Lambda表达式可以捕获闭合作用域中的变量值。在java中,为了确保被捕获的值是被良好定义的,需要遵守一个重要的约束。在Lambda表达式中,被引用的变量的值不可以被更改。
eg:下面这个表达式是不合法的
public static void repeatMessage(String text,int count){Runnable r = () -> {while(count > 0){count--; //错误,不能更改已捕获变量的值System.out.println(text);Thread.yield();}};new Thread(r).start();
}
做出这个约束是有原因的。更改lambda表达式中的变量不是线程安全的。假设有一系列并发的任务,每个线程都会更新一个共享的计数器。
int matches = 0;
for(Path p : files)
new Thread(() -> {if(p中包含某些属性) matches++;}).start(); //非法更改matches的值
Note:matches是“有效final”的(一个有效的final变量被初始化后,就永远不会再被赋一个新值的变量)。在我们的示例中,matches总是引用同一个ArrayList对象,但是,这个对象是可变的,因此是线程不安全的 。如果多个线程同时调用add方法,结果将无法预测。
Lambda表达式的方法体与嵌套代码块有着相同的作用域。因此它也适用同样的命名冲突和屏蔽规则。在Lambda表达式中不允许声明一个与局部变量同名的参数或者局部变量。
Path first = Paths.get("/usr/bin");
Comparator<String> comp = (first,second) ->Integer.compare(first.length(),second.length());
//错误,变量first已经定义了
在一个方法里,你不能有两个同名的局部变量,因此,你也不能在lambda表达式中引入这样的变量。
当你在Lambda表达式中使用this关键字,你会引用创建该Lambda表达式的方法的this参数,
eg:
public class Application{public void doWork(){Runnable runner = () -> {....;System.out.println(this.toString());......};}
}
表达式this.toString()会调用Application对象的toString()方法,而不是Runnable实例的toString()方法。在Lambda表达式中使用this,与在其他地方使用this没有什么不同。Lambda表达式的作用域被嵌套在doWork()方法中,并且无论this位于方法的何处,其意义都是一样的。
相关文章:
Lambda 表达式的作用域
在Lambda表达式中访问外层作用域和旧版本的匿名对象中的方式类似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。 Lambda表达式不会从超类(supertype)中继承任何变量名,也不会引入一个新的作用域。Lambd…...
【portswigger】第二专题-XSS(二)
portswigger 靶场(第二章节)XSS 视频同步更新至bilibili bibi地址 【【portswigger】第二专题-XSS(一前置知识)】 https://www.bilibili.com/video/BV1mp4y157xA/?share_sourcecopy_web 【【portswigger】第二专题-XSSÿ…...
【计算机视觉|人脸建模】3D人脸重建基础知识(入门)
本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 一、三维重建基础 三维重建(3D Reconstruction)是指根据单视图或者多视图的图像重建三维信息的过程。 1. 常见三维重建技术 人工几何模型仪器采集基于图像的建模描述基于几何建模…...
使用Jetpack Glance创建Android Widget
使用Jetpack Glance创建Android Widget Jetpack Glance发布,让我们使用Google提供的Jetpack Glance创建一个联系人列表小部件。 https://developer.android.com/jetpack/compose/glance 什么是Glance? Jetpack Glance是一个使用Kotlin API创建小型、轻…...
【MyBatis 学习三】子段不一致问题 多表查询 动态SQL
目录 一、解决Java实体类属性与数据库表字段不一致问题 🌷现象1:显示字段不对应:使用ResultType查询结果为null; 🌷解决办法:字段不对应:使用ResultMap解决。 二、数据库的多表查询 &#…...
15. Spring AOP 的实现原理 代理模式
目录 1. 代理模式 2. 静态代理 3. 动态代理 3.1 JDK 动态代理 3.2 CGLIB 动态代理 4. JDK 动态代理和 CGLIB 动态代理对比 5. Spring代理选择 6. Spring AOP 实现原理 6.1 织入 7. JDK 动态代理实现 8. CGLIB 动态代理实现 9. 总结 1. 代理模式 代理模式…...
死锁产生的原因以及解决方案
一.原因: 1.使用互斥锁. 2.除非主动释放,负责不能被抢占. 3.占用一把锁不释放,等待其它锁资源(保持现状). 4.锁形成环路. 二.解决方案: 给锁编号,上锁的时候从小到大依次上锁,譬如如果一个线程要上1号和2号两把锁,如果1号锁被占用,不能上2号锁,等其它线程释放1号锁资源后…...
【构造】CF1758 D
Problem - D - Codeforces 题意: 思路: 如果需要构造一个和为定值的序列,那么考虑n-d,n-d1,.....nd-1,nd这种形式 如果要保证不能重复,那么先考虑一个排列,然后在排列上操作 如果根据小数据构造出了一些简单情形&a…...
【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE,Coding Everywhere
【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE,随时随地写代码! 写在最前视频讲解:Cloud Studio活动简介何为腾讯云 Cloud Studio?Cloud Studio简介免费试用,上手无忧Cloud Studio 特点及优势云端开发多种预制环境可选metawo…...
JavaScript将一层级对象数组转为children嵌套的三层级树状对象数组(多级树状分类)
有时候后端返回的数据不适合前端,我们就需要进行转换,比如我想用elementUI的级联选择器,而这个组件对数据格式有要求,本篇文章将介绍如何将一层级对象数组数据格式转为三层级嵌套children数组,JavaScript、Vue、小程序等都适用,使用情景为多级分类,嵌套数据 情况1:原数…...
Windows脚本启动Redis、Java和Nginx服务指南
文章目录 1. 完整的批处理脚本2. Redis服务3. Java服务4. Nginx服务 1. 完整的批处理脚本 echo offcd C:\path\to\redis tasklist /FI "IMAGENAME eq redis-server.exe" 2>NUL | find /I /N "redis-server.exe">NUL if "%ERRORLEVEL%"&qu…...
【宝藏系列】STM32之C语言基础知识
【宝藏系列】STM32之C语言基础知识 文章目录 【宝藏系列】STM32之C语言基础知识1️⃣位操作2️⃣define宏定义3️⃣ifdef条件编译4️⃣extern变量声明5️⃣typedef类型别名 C语言是单片机开发中的必备基础知识,本文列举了部分 STM32 学习中比较常见的一些C语言基础知…...
探索自除数:发现区间内的神奇数字
本篇博客会讲解力扣“728. 自除数”的解题思路,这是题目链接。 对于给定的正整数num,我们如何判断它是不是自除数呢?根据定义,我们只需要把num的每一位数字都取出来,判断能不能整除num,如果发现num的某一位…...
打卡力扣题目四
#左耳听风 ARST 打卡活动重启# 目录 一、题目 二、解题代码 三、解题思路 关于 ARTS 的释义 —— 每周完成一个 ARTS: ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Share: 分享…...
npm yarn nrm
npm 和 yarn npm和yarn都是包管理器,yarn是在2016年发布的,那时npm还处于V3时期,那时候还没有package-lock.json文件,不稳定性、安装速度慢等缺点经常会受到广大开发者吐槽。此时,yarn 诞生了。yarn 的优点,…...
关于我对刚开始学Java的小白想分享的内容:
编程是很有魅力的,让很多人为之痴迷 如果你是初学者,俗称小白,不妨看看下述内容: 文章目录 1. Java 简介 Java 是一门编程语言,发展至今已经成为一门真正意义上的语言标准。 Java是一个完整的平台,有一个…...
Redis学习路线(5)—— Redis生成唯一ID
一、全局唯一ID (一)在用户抢购时,就会生成订单并保存到数据库中,而订单表如果使用自增ID就会存在以下几种情况: 自增ID规律性太强受单表数据量的限制 (二)全局ID生成器,是一种在…...
django后台系统Tyadmin
无意之间发现个django的后台管理框架,仔细与xadmin对比了一下,无论是功能上还是便携性上都与xadmin特别相似,但个人感觉Tyadmin略胜一筹,因为外观上要比xadmin要美观,而且相比起来速度也快,部署甚至也和简单…...
设计模式适合用于解决特定的软件设计问题呢
当我们在开发软件时,经常会遇到各种各样的问题和挑战,例如如何处理对象之间的关系、如何实现复杂的业务逻辑、如何处理并发访问等。这些问题都是软件设计中经常遇到的问题,而设计模式就是为了解决这些问题而诞生的。 以下是一些常见的软件设…...
测试|测试分类
测试|测试分类 文章目录 测试|测试分类1.按照测试对象分类(部分掌握)2.是否查看代码:黑盒、白盒灰盒测试3.按开发阶段分:单元、集成、系统及验收测试4.按实施组织分:α、β、第三方测试5.按是否运行代码:静…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
