Lambda表达式常见的Local variable must be final or effectively final原因及解决办法

news2024/9/28 15:25:59

目录

  • Local variable must be final or effectively final
    • 错误原因
  • 解决办法
    • 按照要求定义为final(不符合实情,很多时候是查库获取的变量值)
    • 使用原子类存储变量,保证一致性
      • AtomicReference
      • 常用原子类
  • 其它

Local variable must be final or effectively final

错误原因

  • 在内部类或匿名内部类中引用了一个在外部类中定义的局部变量,那么这个局部变量必须是 finaleffectively final

    • Final 变量:指一旦被赋值后不能再修改的变量。
    • Effectively Final 变量:没有显式声明为 final,但是在变量初始化后没有被再次赋值的变量。
  • 为什么要求局部变量是 finaleffectively final ,为了保持一致性

    • 内部类引用了外部类的局部变量时,实际上内部类会持有该局部变量的一个副本。由于内部类的生命周期可以超过外部方法的执行周期,如果外部方法的局部变量是可修改的,那么当该方法结束后,局部变量可能已经被修改,而内部类还要继续使用旧的值,这就会导致不一致性和错误的结果
  • Lambda表达式经常遇到这种错是因为它本质上是一个匿名内部类的简化写法。因此需要符合 Local variable must be final or effectively final的规则

解决办法

按照要求定义为final(不符合实情,很多时候是查库获取的变量值)

使用原子类存储变量,保证一致性

Java8API官网

AtomicReference

AtomicReference
在这里插入图片描述
我们在这里主要使用set方法存储,以及通过get方法调用

  • 比如存储map,调用map

    // 存储Map,并且初始化new HashMap<>(),防止空指针
    AtomicReference<Map<Long, List<TestEntity>>> atomicMap = new AtomicReference<>(new HashMap<>());
    //具体逻辑代码,获取map值
    List<TestEntity> entities = this.selectList(null);
    if (CollectionUtils.isNotEmpty(scriptRelationEntities)) {
       Map<Long, List<TestEntity>> map = entities.stream().collect(Collectors.groupingBy(TestEntity::getId));
        if (map != null) {
        	//将map存放到atomicMap 
            atomicMap .set(map);
        }
    }
    //调用map,直接get()
    if(!atomicMap.get().isEmpty(){
    	atomicMap.get().forEach((key, value) -> {});
    }
    
    

    在这里插入图片描述
    在这里插入图片描述

  • 存储list

    AtomicReference<List<TestEntity>> atomicList = new AtomicReference<>(new ArrayList<>());
    

常用原子类

  • AtomicBoolean:用于对boolean值进行原子操作。

    AtomicBoolean atomicBoolean = new AtomicBoolean(true);
    boolean value = atomicBoolean.get(); // 获取当前boolean值
    atomicBoolean.set(false); // 设置新的boolean值
    boolean success = atomicBoolean.compareAndSet(true, false); // 比较并更新值
    

    比如跳出结束循环
    在这里插入图片描述

  • AtomicInteger:用于对int值进行原子操作。

    AtomicInteger atomicInteger = new AtomicInteger(0);
    int value = atomicInteger.get(); // 获取当前int值
    atomicInteger.set(5); // 设置新的int值
    int newValue = atomicInteger.incrementAndGet(); // 原子递增并获取新值
    
  • AtomicLong:用于对long值进行原子操作。

    AtomicLong atomicLong = new AtomicLong(0L);
    long value = atomicLong.get(); // 获取当前long值
    atomicLong.set(10L); // 设置新的long值
    long newValue = atomicLong.addAndGet(5L); // 原子增加并获取新值
    
  • AtomicReference:用于对对象引用进行原子操作。

    AtomicReference<String> atomicRef = new AtomicReference<>("Hello");
    String oldValue = atomicRef.get(); // 获取当前引用值
    atomicRef.set("World"); // 设置新的引用值
    boolean success = atomicRef.compareAndSet("World", "NewValue"); // 比较并更新
    
  • AtomicReferenceArray:用于对对象引用数组进行原子操作。

    AtomicReferenceArray<String> atomicArray = new AtomicReferenceArray<>(new String[]{"Hello", "World"});
    String value = atomicArray.get(0); // 获取索引0处的引用值
    atomicArray.set(1, "NewValue"); // 设置索引1处的引用值
    boolean success = atomicArray.compareAndSet(0, "Hello", "UpdatedValue"); // 比较并更新
    
  • AtomicIntegerFieldUpdater:通过反射方式实现对指定类的int字段进行原子操作。

  • AtomicLongFieldUpdater:通过反射方式实现对指定类的long字段进行原子操作。

  • AtomicReferenceFieldUpdater:通过反射方式实现对指定类的引用字段进行原子操作。

  • AtomicStampedReference:带有版本号的原子引用,用于解决ABA问题。

  • AtomicMarkableReference:带有标记位的原子引用,用于解决标记并搭配引用的场景。

其它

AtomicReference<List<String>> 是否等价 AtomicReferenceArray<String>

  • 不等价
    • AtomicReference<List<String>> 是一个持有 List<String> 对象引用的 AtomicReference。它提供原子操作来更新和访问对 List<String> 对象的引用。你可以通过 AtomicReference 持有的引用来修改和获取列表的内容。
AtomicReference<List<String>> atomicRef = new AtomicReference<>(new ArrayList<>());
List<String> list = atomicRef.get(); // 获取当前列表的引用
list.add("Hello"); // 通过引用修改列表
atomicRef.set(new ArrayList<>()); // 更新对新列表的引用
  • AtomicReferenceArray<String> 是一个持有 String 对象数组AtomicReferenceArray。它提供原子操作来更新和访问数组指定索引位置的元素。你可以原子化地修改和访问数组的值。
AtomicReferenceArray<String> atomicArray = new AtomicReferenceArray<>(new String[5]);
String value = atomicArray.get(0); // 获取索引0处的值
atomicArray.set(1, "Hello"); // 设置索引1处的值
boolean success = atomicArray.compareAndSet(2, "OldValue", "NewValue"); // 比较并设置索引2处的值

AtomicReference<List> 操作的是单个对 List 对象的引用,而 AtomicReferenceArray 操作的是一个数组中的元素,每个元素都有独立的索引。因此,根据要操作的数据结构是单个引用对象还是数组,选择合适的原子类非常重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/804738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(树) 剑指 Offer 07. 重建二叉树 ——【Leetcode每日一题】

❓剑指 Offer 07. 重建二叉树 难度&#xff1a;中等 输入某二叉树的 前序遍历 和 中序遍历 的结果&#xff0c;请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 示例 1: Input: preorder [3,9,20,15,7], inorder [9,3,15,20,7] …

8.11 PowerBI系列之DAX函数专题-TopN中实现N的动态

需求 实现 1 ranking by amount rankx(allselected(order_2[产品名称]),[total amount]) 2 rowshowing_boolean var v_ranking [ranking by amount] var v_topN-no [topN参数 值] var v_result int( v_ranking < v_topN_no) return v_result 3 将度量值2放入视觉对象筛…

spinal HDL语法学习

1 赋值语句 用来声明变量 : 用来对变量进行赋值 2 when otherwise前面是否有"."与otherwise是否换行有关系 3 case class 对Bundle进行扩展时&#xff0c;需要case class case class和class主要有两点区别&#xff1a; &#xff08;1&#xff09;case class不需…

会议OA项目之会议发布(一)

目录 前言&#xff1a; 会议发布的产品原型图&#xff1a; 1.会议发布 1.1实现的特色功能&#xff1a; 1.2思路&#xff1a; 使用的数据库&#xff1a; 我们要实现多功能下拉框的形式选择可以参考原文档&#xff1a;https://hnzzmsf.github.io/example/example_v4.html#down…

运算放大器--------加减运算电路

反向求和运算电路 电路 公式 同向加法运算电路 电路 公式 加减运算电路 分别求正向输入的输出和反相输入的输出&#xff0c;然后求和就可以得到到最终的输出。 切记&#xff0c;虚短虚断不是真正的断路和短路。

antDesign的a-select数据回显选中initialValue问题解决方法

在开发过程中表单中的【学习专业】下拉列表项需要数据回显&#xff0c;设置了initialValue&#xff0c;但只显示下拉选项的majorId值, 没有显示具体的专业名称&#xff0c;经排查发现是majorId数据类型导致的&#xff0c;下拉选项majorList数组中的id是数值类型&#xff0c;而在…

LeetCode|backtracking|review:40. 131. 93. 47. 332. | 37. Sudoku Solver

复习&#xff1a; 40. Combination Sum II [1,1,2,3]中&#xff0c;答案里有[1,1,2], 但是不能有两个[1,2,3] 131. Palindrome Partitioning 每个for都是在给定的start之后找一个palindrome。当start 93. Restore IP Addresses forloop每次loop都是在给定的start的后三个数…

Redis三种模式——主从复制,哨兵模式,集群

目录 一、主从复制 1.1主从复制的概念 1.2Redis主从复制作用 1.2.1数据冗余 1.2.2故障恢复 1.2.3负载均衡 1.2.4高可用基石 1.3Redis主从复制流程 1.4部署Redis 主从复制 1.4.1.环境部署 1.4.2.所有服务器都先关闭防火墙 1.4.3.所有服务器都安装Redis 1.4.4修改Master主节点R…

IFIX5.8安装教程

管理员身份运行&#xff1a; 安装&#xff1a; 下次安装的时候选择SCADA服务器&#xff0c;独立。然后下图就不会出现了。 重启电脑&#xff1a;

【2050. 并行课程 III】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个整数 n &#xff0c;表示有 n 节课&#xff0c;课程编号从 1 到 n 。同时给你一个二维整数数组 relations &#xff0c;其中 relations[j] [prevCoursej, nextCoursej] &#xff0c;表示课程…

SkyEye与Jenkins的DevOps持续集成解决方案

在技术飞速发展的当下&#xff0c;随着各行各业的软件逻辑复杂程度提升带来的需求变更&#xff0c;传统测试已无法满足与之相对应的一系列测试任务&#xff0c;有必要引入一个自动化、可持续集成构建的DevOps平台来解决此类问题。本文将主要介绍SkyEye与Jenkins的持续集成解决方…

MySQL基础扎实——Like声明中的%什么意思

语意讲解 在MySQL的LIKE语句中&#xff0c;%是一个通配符&#xff0c;用于匹配任意长度&#xff08;包括零长度&#xff09;的字符序列。 具体来说&#xff0c;当使用%放置在LIKE语句中的模式中时&#xff0c;它表示可以匹配任意字符的序列。这个字符序列可以是零个字符、一个…

VOC 格式与 YOLO 格式的相互转换

目录 数据集介绍VOC 格式转换为 YOLO 格式YOLO 格式转换为 VOC 格式 数据集介绍 本文使用的数据集是自制的安全帽数据集&#xff0c;共含有 6696 张图片&#xff0c;部分图片如下&#xff1a; 以及对应的 6696 个 VOC 格式的 xml 标注文件&#xff0c;部分文件如下&#xff1a…

[Linux]进程间通信

[Linux]进程间通信 文章目录 [Linux]进程间通信进程间通信什么是进程间通信进程间通信的目的进程间通信的本质为什么存在进程间通信进程间通信的分类 管道什么是管道匿名管道本质pipepipe的使用匿名管道读写情况匿名管道的特征 命名管道本质命令行创建命名管道创建和删除命名管…

SolidWorks绘制Maxwell仿真用带桥接的三维平板螺旋线圈

文章目录 前言一、建立涡状线二、拉伸方法1&#xff08;建立工作面&#xff0c;较复杂&#xff09;三、拉伸方法2&#xff08;穿透&#xff0c;较简单&#xff09;四、建立桥接 前言 在使用Maxwell进行电磁场仿真时&#xff0c;经常需要绘制各种异形线圈&#xff0c;由于Maxwel…

5.定时器-间歇函数

网页中经常会需要一种功能&#xff1a;每隔一段时间需要自动执行一段代码&#xff0c;不需要我们手动去触发 例如&#xff1a;网页中的倒计时 ●要实现这种需求&#xff0c;需要定时器函数 5.1开启定时器 语法 setInterval(函数,间隔时间)作用&#xff1a;每隔一段时间调用这…

Spring 6【单例设计模式、bean标签的scope属性、Spring 循环注入问题】(八)-全面详解(学习总结---从入门到深化)

目录 十五、单例设计模式 十六、bean标签的scope属性 十七、Spring 循环注入问题 十五、单例设计模式 设计模式&#xff1a;根据面向对象五大设计思想衍生出的23种常见代码写法&#xff0c;每种写法可以专门解决一类问题。 单例设计模式&#xff1a;保证某个类在整个应用程…

一文搞懂加密和接口签名小知识

最近在做的接口自动化测试工程中&#xff0c;一些接口需要签名&#xff0c;涉及到了加解密的一些知识&#xff0c;顺手梳理了下&#xff0c;分享给大家。 主要分为四个部分介绍&#xff1a; 一、基础概念 二、加密算法介绍 三、接口签名 四、实例分析 一、基础概念 加密是…

Leetcode 27 移除元素 代码逐行讲解

Leetcode 27 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考…

Go语言中的结构体详解

关于 Golang 结构体 Golang 中没有“类”的概念&#xff0c;Golang 中的结构体和其他语言中的类有点相似。和其他面向对 象语言中的类相比&#xff0c;Golang 中的结构体具有更高的扩展性和灵活性。 Golang 中的基础数据类型可以表示一些事物的基本属性&#xff0c;但是当我们…