为什么lamda不能修改外部引用的变量?

    lamda表达式实际上一个匿名内部类 所以我们的问题可以转向这两个问题: 为什么匿名内部类调用外部引用的时候,外部引用需要用final修饰? lamda如果才能修改外部引用变量?

1. 为什么匿名内部类调用外部引用的时候,外部引用需要用final修饰?

    我们在内部类中调用外部的自由变量,即使该变量没有显式的声明final,但是在编译器解析的时候也被定义成一个final变量 这里java内部类引用外部变量近似闭包的概念。我们先来了解一下js中满足闭包的条件: 一个依赖于外部环境自由变量的函数 这个函数能够访问外部环境里的自由变量 闭包常见使用场景 回调函数 匿名函数 在闭包中访问外部自由变量访问的是自由变量的哪个值呢? 是闭包定义时,自由变量所定义的值(非运行时!) js中通常我们要解决闭包导致对象不正确问题,常用的有四个解决方案: func.call(obj, 20, 30) func.apply(obj, [20,30]) const func1 = func.bind(obj,20,30) 在闭包外方法中手动指定 let self = this 说到闭包,绕不开this指向问题,this应该指向的是运行时的对象,简单总结this指向三种情况: obj.func() -> this指向.前面调用的对象,此时指向obj new Fun() -> this指向new出来的对象 函数自调、匿名函数和回调函数 -> this指向的是window java对闭包的处理 如函数在使用类的全局变量的时候 全局变量实际是类的一个属性,用this指向,可所以修改 但是在处理匿名内部类的时候,在不同的类中无法用this指向,这时java的做法是: 将自由变量拷贝一个副本带给匿名内部类,供内部类使用。 类似于值传递而非引用传递

2. lamda如果才能修改外部引用变量?

  1. 数组
  2. 全局变量
  3. atomicReference

3. 划重点

lamda不能修改外部引用的变量的原因其实也很简单,本质上就是因为lambda表达式在方法内部,那么lambda表达式的内存分配就是在栈上。栈内存不存在线程安全问题,因为栈内存存的都是变量的副本。
对于局部变量count而言,它的生命周期就是所在方法的生命周期。这就决定了count无法被位于同一个栈帧上的lambda修改,因为这种修改毫无意义,
你无法将你的修改传递出当前栈帧。栈内存不会被共享,也就意味着你没有权利和其他栈帧通信。

如果非要在lambda内部修改lambda表达式外部的局部变量的值呢?
有两种方式:使用数组或者把局部变量定义为全局变量。

这2种方式,其实本质是一样的:内存都分配在堆上。这就决定了,使用这2种方式来修改变量的值,是可行的。

经验分享 程序员 微信小程序 职场和发展