背景

今天组里面有一个新同事小A向我求助了一个问题,比较典型也是新人很容易犯的问题,特此记录下来。

他写了一个类似于下面的代码

package com.lingyejun.dating.chap11.toutiao;import java.util.*;
import java.util.stream.Collectors;public class StreamMapCopy {public static List<Phone> initPhoneList() {List<Phone> phones = new ArrayList<>();Phone phone1 = new Phone(1, "iPhone 11 Pro", "银色", "64GB", 8699);Phone phone2 = new Phone(2, "iPhone 11 Pro", "银色", "64GB", 8700);Phone phone3 = new Phone(3, "iPhone 11 Pro Max", "银色", "64GB", 8900);phones.add(phone1);phones.add(phone2);phones.add(phone3);return phones;}public static void main(String[] args) {List<String> queryPhoneNameList = Arrays.asList("iPhone 11 Pro", "HuaWei", "Oppo", "Vivo");Map<String, List<Phone>> otherMap = new HashMap<>();if (queryPhoneNameList.size() > 0) {Map<String, List<Phone>> phoneMap = initPhoneList().stream().filter(a -> queryPhoneNameList.contains(a.getProductName())).collect(Collectors.groupingBy(Phone::getProductName));// 这种写法下面的forEach循环中使用到的otherMap编译不过去,// Variable used in lambda expression should be final or effectively final//otherMap = phoneMap;// 将逻辑放到方法中可以绕过此逻辑copyMap(otherMap, phoneMap);}queryPhoneNameList.forEach(queryPhoneName -> {otherMap.get(queryPhoneName);});}private static void copyMap(Map<String, List<Phone>> sourceMap, Map<String, List<Phone>> targetMap) {// 方法参数是值传递,故这种赋值是不会生效的targetMap = sourceMap;// 改为下面的方式就可以了targetMap.putAll(sourceMap);}
}

问题

一开始是编译不过去的

Variable used in lambda expression should be final or effectively final

翻译过来就是说在lambda表达式中只能引用标记了 final 的外层局部变量或者虽然没有显式定义为final,但实际上就是一个final变量,否则会编译错误。

那么显然在上面的代码中的otherMap变量,在Map<String, List<Phone>> otherMap = new HashMap<>();初始化以后,又进行了一次赋值操作otherMap = phoneMap;进行了二次修改,所以编译器认为这不是一个final变量故而报错。

但是我们可以用一些技巧来规避掉这个报错,比如小A的写法,他将otherMap = phoneMap;对象赋值的方法拷贝出来放到了方法里面

    private static void copyMap(Map<String, List<Phone>> sourceMap, Map<String, List<Phone>> targetMap) {targetMap = sourceMap;}

然后问题就出现了,小A debug了一下发现执行完copyMap(phoneMap, otherMap);之后otherMap仍然是空的,然后翎野君一下子看出了其中的门道,然后给他讲了一下java中方法参数传递实际上是值传递的,之前还专门写过一篇文章辨析Java方法参数中的值传递和引用传递

将这个文章看完相信大家就懂得了其中的原有,因为Map有putAll().它把一个Map的所有元素全部复制到另一个Map中,所以将方法改成如下就可以了

    private static void copyMap(Map<String, List<Phone>> sourceMap, Map<String, List<Phone>> targetMap) {targetMap.putAll(sourceMap);}

本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。

首发链接:规避Variable used in lambda expression should be final or effectively final而引发了方法参数值拷贝的问题 - 翎野君 - 博客园

规避Variable used in lambda expression should be final or effectively final而引发了方法参数值拷贝的问题相关推荐

  1. 深入浅出理解 Variable used in lambda expression should be final or effectively final

    翻译:lambda 表达式中使用的变量应该是 final 或者有效的 final 原因解析:lambda表达式(多用在线程领域),是由匿名内部类演变来的. 匿名内部类产生的对象一般存放在JVM的堆区域 ...

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

    作者 | 沉默王二 来源 | CSDN博客专家 出品 | CSDN(ID:CSDNnews) 偶尔,我们需要在 Lambda 表达式中修改变量的值,但如果直接尝试修改的话,编译器不会视而不见听而不闻, ...

  3. java nextintln_java – 从lambda表达式引用的局部变量必须是final或者有效的final

    我有一个JavaFX 8程序(适用于JavaFXPorts交叉平台),它实际上是为了做我想做的事情,但却是一步之遥.程序读取文本文件,对行进行计数以建立随机范围,从该范围中选取一个随机数并读取该行以进 ...

  4. foreach无法给外部变量赋值(Local variable decimal defined in an enclosing scope must be final or effectively )

    报错信息如下: Local variable decimal defined in an enclosing scope must be final or effectively final 原因:在 ...

  5. [原创]深入理解C# 3.x的新特性(3):从Delegate、Anonymous Method到Lambda Expression

    较之前一个版本,对于C# 3.x和VB 9来说,LINQ是最具吸引力的.基本上很多的新的特性都是围绕着LINQ的实现来设计的.借助Extension Method,我们可以为LINQ定义一系列的Ope ...

  6. 0x55——C#中的Lambda Expression

    本文主要参考MSDN上的Lambda Expression(C# Programming Guide),博文Lambda Expression和code project上的博文Exploring La ...

  7. java lambda函数_Java SE 8新功能介绍:使用Lambda Expression进行函数式编程

    java lambda函数 " Java SE 8新功能浏览 "系列的这篇文章将深入了解Lambda表达式 . 我将向您展示Lambda表达式的几种不同用法. 它们都具有功能接口的 ...

  8. Java SE 8新特性导览:使用Lambda Expression进行函数式编程

    " Java SE 8新功能浏览 "系列的这篇文章将深入了解Lambda表达式 . 我将向您展示Lambda表达式的几种不同用法. 它们都具有功能接口的共同实现. 我将解释编译器如 ...

  9. C#体贴之处点滴 - extention method, lambda expression, anonymous method

    说的是C#如何体贴程序员,而非.NET Framework. 这是C#对Delegate相关领域下的精微功夫:     List<Product> products = Product.G ...

  10. IDEA:Lambda expression are not supported at language level ‘5‘

    错误 Lambda expression are not supported at language level '5' Error:(28, 39) java: -source 1.5 中不支持 l ...

最新文章

  1. 花了一个星期,我终于把RPC框架整明白了!
  2. php主要算法设计,四种排序算法设计(PHP)
  3. python打包成exe闪退_脚本程序打包后,黑框一闪而过,程序不能运行
  4. python表白代码照片墙-python入会生成照片墙 利用python生成照片墙代码
  5. oracle 如何创建序列squence
  6. 【飞秋】记一次“偷盗”别人的CSS和Js
  7. 学习经验浅谈——论做学习笔记的重要性
  8. jq往字符串中插入_jq: dom-插入
  9. 如何自建微信外卖平台_外卖平台高抽成的背后,看小程序如何玩转餐饮外卖?...
  10. python学习——正则表达项目
  11. Codeforces Round 1299 简要题解
  12. altium designer PCB各层介绍+添加多层+设置正/负片+设置层的网络标号
  13. 人力资源管理专业知识与实务(中级)
  14. 网络安全---数字签名
  15. 一名合格的大数据测试工程师,需要掌握哪些基本知识
  16. 如何在windows 10或11下制作外接便携式可移植启动盘(以安装最新的ubuntu 22.04为例)
  17. unity 控制点 贝塞尔曲线_在Unity中使用贝塞尔曲线(转)
  18. kibana java_Kibana安装及使用说明
  19. 浙大计算机学院博士毕业论文要求,浙大在读博士需要3篇SCI 论文才能毕业,清华博士却不作要求!...
  20. Python爬取豌豆荚软件分类

热门文章

  1. 高中数学一轮复习逆袭必要学习方法
  2. C语言中的细节知识点(五)
  3. 如果“永远”只是一瞬间
  4. 数值分析常用的几个小程序C++实现
  5. 调用快递鸟API查询物流
  6. 分库分表之MyCat应用
  7. 资产证券化:国际借鉴与中国实践案例 读后感
  8. 行测 加强题型 加强论证
  9. 黑色星期五:纳斯达克五大科技股市值单日蒸发约1000亿美元
  10. html播放器怎么删除,风行如何完全删除?风行播放器彻底删除图文教程汇总