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

本文主要是介绍Lambda表达式常见的Local variable must be final or effectively final原因及解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

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

这篇关于Lambda表达式常见的Local variable must be final or effectively final原因及解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/260080

相关文章

Python中的sort方法、sorted函数与lambda表达式及用法详解

《Python中的sort方法、sorted函数与lambda表达式及用法详解》文章对比了Python中list.sort()与sorted()函数的区别,指出sort()原地排序返回None,sor... 目录1. sort()方法1.1 sort()方法1.2 基本语法和参数A. reverse参数B.

前端导出Excel文件出现乱码或文件损坏问题的解决办法

《前端导出Excel文件出现乱码或文件损坏问题的解决办法》在现代网页应用程序中,前端有时需要与后端进行数据交互,包括下载文件,:本文主要介绍前端导出Excel文件出现乱码或文件损坏问题的解决办法,... 目录1. 检查后端返回的数据格式2. 前端正确处理二进制数据方案 1:直接下载(推荐)方案 2:手动构造

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

Redis高性能Key-Value存储与缓存利器常见解决方案

《Redis高性能Key-Value存储与缓存利器常见解决方案》Redis是高性能内存Key-Value存储系统,支持丰富数据类型与持久化方案(RDB/AOF),本文给大家介绍Redis高性能Key-... 目录Redis:高性能Key-Value存储与缓存利器什么是Redis?为什么选择Redis?Red

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

javacv依赖太大导致jar包也大的解决办法

《javacv依赖太大导致jar包也大的解决办法》随着项目的复杂度和依赖关系的增加,打包后的JAR包可能会变得很大,:本文主要介绍javacv依赖太大导致jar包也大的解决办法,文中通过代码介绍的... 目录前言1.检查依赖2.更改依赖3.检查副依赖总结 前言最近在写项目时,用到了Javacv里的获取视频

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

MySQL ORDER BY 语句常见用法、示例详解

《MySQLORDERBY语句常见用法、示例详解》ORDERBY是结构化查询语言(SQL)中的关键字,隶属于SELECT语句的子句结构,用于对查询结果集按指定列进行排序,本文给大家介绍MySQL... 目录mysql ORDER BY 语句详细说明1.基本语法2.排序方向详解3.多列排序4.常见用法示例5.

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda