百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

编译器说 Lambda 表达式中的变量必须是 final 的,我偏不信 | 原力计划

ztj100 2024-12-20 19:51 22 浏览 0 评论

作者 | 沉默王二

来源 | CSDN博客专家

出品 | CSDN(ID:CSDNnews)

偶尔,我们需要在 Lambda 表达式中修改变量的值,但如果直接尝试修改的话,编译器不会视而不见听而不闻,它会警告我们说:“variable used in lambda expression should be final or effectively final”。

这个问题发生的原因是因为 Java 规范中是这样规定的:

Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression

must either be declared final or be effectively final (§4.12.4),

or a compile-time error occurs where the use is attempted.

大致的意思就是说,Lambda 表达式中要用到的,但又未在 Lambda 表达式中声明的变量,必须声明为 final 或者是 effectively final,否则就会出现编译错误。

关于 final 和 effectively final 的区别,可能有些小伙伴不太清楚,这里多说两句。

 1final int a;
2a = 1;
3// a = 2;
4// 由于 a 是 final 的,所以不能被重新赋值
5
6int b;
7b = 1;
8// b 此后再未更改
9// b 就是 effectively final
10
11int c;
12c = 1;
13// c 先被赋值为 1,随后又被重新赋值为 2
14c = 2;
15// c 就不是 effectively final

明白了 final 和 effectively final 的区别后,我们了解到,如果把 limit 定义为 final,那就无法在 Lambda 表达式中修改变量的值。那有什么好的解决办法呢?既能让编译器不发出警告,又能修改变量的值。

思前想后,试来试去,我终于找到了 3 个可行的解决方案:

1)把 limit 变量声明为 static。

2)把 limit 变量声明为 AtomicInteger。

3)使用数组。

下面我们来详细地一一介绍下。

把 limit 变量声明为 static

要想把 limit 变量声明为 static,就必须将 limit 变量放在 main 方法外部,因为 main 方法本身是 static 的。完整的代码示例如下所示。

 1public class ModifyVariable2StaticInsideLambda {
2 static int limit = 10;
3 public static void main(String[] args) {
4 Runnable r = -> {
5 limit = 5;
6 for (int i = 0; i < limit; i++) {
7 System.out.println(i);
8 }
9 };
10 new Thread(r).start;
11 }
12}

来看一下程序输出的结果:

10
21
32
43
54

OK,该方案是可行的。

把 limit 变量声明为 AtomicInteger

AtomicInteger 可以确保 int 值的修改是原子性的,可以使用 set 方法设置一个新的 int 值,get 方法获取当前的 int 值。

 1public class ModifyVariable2AtomicInsideLambda {
2 public static void main(String[] args) {
3 final AtomicInteger limit = new AtomicInteger(10);
4 Runnable r = -> {
5 limit.set(5);
6 for (int i = 0; i < limit.get; i++) {
7 System.out.println(i);
8 }
9 };
10 new Thread(r).start;
11 }
12}

来看一下程序输出的结果:

10
21
32
43
54

OK,该方案也是可行的。

使用数组

使用数组的方式略带一些欺骗的性质,在声明数组的时候设置为 final,但更改 int 的值时却修改的是数组的一个元素。

 1public class ModifyVariable2ArrayInsideLambda {
2 public static void main(String[] args) {
3 final int limits = {10};
4 Runnable r = -> {
5 limits[0] = 5;
6 for (int i = 0; i < limits[0]; i++) {
7 System.out.println(i);
8 }
9 };
10 new Thread(r).start;
11 }
12}

来看一下程序输出的结果:

10
21
32
43
54

OK,该方案也是可行的。

好了,亲爱的读者朋友,以上就是本文的全部内容了,是不是感觉挺有意思的,编译器告诉我们要用 final 修饰 Lambda 表达式外的变量,但我们却找到了其他的解决方案,还一找就是 3 个,是不是感觉技能包又升级了,有没有?伸出小手给自己点个赞吧。

PS:本篇文章中的示例代码已经同步到码云,传送门

https://gitee.com/qing_gee/JavaPoint/tree/master

原文链接:

https://blog.csdn.net/qing_gee/article/details/104438986

相关推荐

30天学会Python编程:16. Python常用标准库使用教程

16.1collections模块16.1.1高级数据结构16.1.2示例...

强烈推荐!Python 这个宝藏库 re 正则匹配

Python的re模块(RegularExpression正则表达式)提供各种正则表达式的匹配操作。...

Python爬虫中正则表达式的用法,只讲如何应用,不讲原理

Python爬虫:正则的用法(非原理)。大家好,这节课给大家讲正则的实际用法,不讲原理,通俗易懂的讲如何用正则抓取内容。·导入re库,这里是需要从html这段字符串中提取出中间的那几个文字。实例一个对...

Python数据分析实战-正则提取文本的URL网址和邮箱(源码和效果)

实现功能:Python数据分析实战-利用正则表达式提取文本中的URL网址和邮箱...

python爬虫教程之爬取当当网 Top 500 本五星好评书籍

我们使用requests和re来写一个爬虫作为一个爱看书的你(说的跟真的似的)怎么能发现好书呢?所以我们爬取当当网的前500本好五星评书籍怎么样?ok接下来就是学习python的正确姿...

深入理解re模块:Python中的正则表达式神器解析

在Python中,"re"是一个强大的模块,用于处理正则表达式(regularexpressions)。正则表达式是一种强大的文本模式匹配工具,用于在字符串中查找、替换或提取特定模式...

如何使用正则表达式和 Python 匹配不以模式开头的字符串

需要在Python中使用正则表达式来匹配不以给定模式开头的字符串吗?如果是这样,你可以使用下面的语法来查找所有的字符串,除了那些不以https开始的字符串。r"^(?!https).*&...

先Mark后用!8分钟读懂 Python 性能优化

从本文总结了Python开发时,遇到的性能优化问题的定位和解决。概述:性能优化的原则——优化需要优化的部分。性能优化的一般步骤:首先,让你的程序跑起来结果一切正常。然后,运行这个结果正常的代码,看看它...

Python“三步”即可爬取,毋庸置疑

声明:本实例仅供学习,切忌遵守robots协议,请不要使用多线程等方式频繁访问网站。#第一步导入模块importreimportrequests#第二步获取你想爬取的网页地址,发送请求,获取网页内...

简单学Python——re库(正则表达式)2(split、findall、和sub)

1、split():分割字符串,返回列表语法:re.split('分隔符','目标字符串')例如:importrere.split(',','...

Lavazza拉瓦萨再度牵手上海大师赛

阅读此文前,麻烦您点击一下“关注”,方便您进行讨论和分享。Lavazza拉瓦萨再度牵手上海大师赛标题:2024上海大师赛:网球与咖啡的浪漫邂逅在2024年的上海劳力士大师赛上,拉瓦萨咖啡再次成为官...

ArkUI-X构建Android平台AAR及使用

本教程主要讲述如何利用ArkUI-XSDK完成AndroidAAR开发,实现基于ArkTS的声明式开发范式在android平台显示。包括:1.跨平台Library工程开发介绍...

Deepseek写歌详细教程(怎样用deepseek写歌功能)

以下为结合DeepSeek及相关工具实现AI写歌的详细教程,涵盖作词、作曲、演唱全流程:一、核心流程三步法1.AI生成歌词-打开DeepSeek(网页/APP/API),使用结构化提示词生成歌词:...

“AI说唱解说影视”走红,“零基础入行”靠谱吗?本报记者实测

“手里翻找冻鱼,精心的布局;老漠却不言语,脸上带笑意……”《狂飙》剧情被写成歌词,再配上“科目三”背景音乐的演唱,这段1分钟30秒的视频受到了无数网友的点赞。最近一段时间随着AI技术的发展,说唱解说影...

AI音乐制作神器揭秘!3款工具让你秒变高手

在音乐创作的领域里,每个人都有一颗想要成为大师的心。但是面对复杂的乐理知识和繁复的制作过程,许多人的热情被一点点消磨。...

取消回复欢迎 发表评论: