被匿名内部类引用的变量会被拷贝一份到内部类的环境中

但其后,在外部,该变量如果被修改,则内部外部不一致

Java为了避免数据不同步的问题,做出了匿名内部类只可以访问final的局部变量的限制。

究其原因,在于 区域变量 x 并不是真正被拿来于内部匿名类别中使用,而是在内部匿名类别中复制一份,作为field成员来使用,由于是复本,即便您在内部匿名类别中对 x 作了修改,会不会影响真正的区域变量 x,事实上您也通不过编译器的检查,因为编译器要求您加上"final"关键词,这样您就知道您不能在内部匿名类别中改变 x 的值。

总结下来就是:

  • Java设计者想要匿名函数或者Lambda函数内部外部保持数据一致性(知道了目的才好理解)
  • 然而Java只是实现了capture-by-value形式的闭包,也就是匿名函数内部会重新拷贝一份自由变量(参考答案中闭包的概念),然后函数外部函数内部就有两份数据
  • 那么要想实现1中的目的,只能要求两处变量不变。JDK8之前要求使用final修饰,JDK8聪明些了,可以使用effectively final的方式。java8里不用final修饰局部变量也可以编译通过。总之,两边不变就行了。

https://www.zhihu.com/question/21395848

匿名内部类中使用的外部局部变量为什么只能是final变量的更多相关文章

  1. 为什么匿名内部类只能访问final变量【转】

    是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final.因为虽然匿名内部类在方法的内部,但实际编译的时候, ...

  2. Java 匿名内部类 只能访问final变量的原因

    文章来源:http://blog.sina.com.cn/s/blog_4b6f8d150100qni2.html 1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方 ...

  3. 匿名内部类和局部内部类只能访问final变量的原因

    以下是从各大网站找来的解释,我在这里摘抄一些从其他地方搬过来的大致思想,可能会比较乱, 详细解释 http://blog.csdn.net/salahg/article/details/7529091 ...

  4. 为什么匿名内部类和局部内部类只能访问final变量

    因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或 ...

  5. 从垃圾回收机制解析为什么局部内部类只能访问final修饰的局部变量以及为什么加final能解决问题

    我们先稍微看一下代码: 从这里的提示可以看到,必须要将a的修饰符变为final才行. 现在笔者就这一结果做出自己的分析: 首先来说,我们知道,方法被调用时会执行,当执行的时候,方法中的局部变量会加载到 ...

  6. 为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰

    大部分时候,类被定义成一个独立的程序单元.在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类. class Outer { priv ...

  7. [多问几个为什么]为什么匿名内部类中引用的局部变量和参数需要final而成员字段不用?(转)

    昨天有一个比较爱思考的同事和我提起一个问题:为什么匿名内部类使用的局部变量和参数需要final修饰,而外部类的成员变量则不用?对这个问题我一直作为默认的语法了,木有仔细想过为什么(在分析完后有点印象在 ...

  8. JAVA中内部类(匿名内部类)访问的局部变量为什么要用final修饰?

    本文主要记录:在JAVA中,(局部)内部类访问某个局部变量,为什么这个局部变量一定需要用final 关键字修饰? 首先,什么是局部变量?这里的局部是:在方法里面定义的变量. 因此,内部类能够访问某局部 ...

  9. 匿名内部类为什么访问外部类局部变量必须是final的?

    1.内部类里面使用外部类的局部变量时,其实就是内部类的对象在使用它,内部类对象生命周期中都可能调用它,而内部类试图访问外部方法中的局部变量时,外部方法的局部变量很可能已经不存在了,那么就得延续其生命, ...

随机推荐

  1. solt插槽的使用。

    在组件内template中使用 <slot name='header'></slot> 在页面内 直接添加标签 如 <hs><h1 slot='header' ...

  2. free命令详解

    free的命令详解   free命令可以显示当前系统未使用的和已使用的内存数目,还可以显示被内核使用的内存缓冲区. 语法 free [选项] 选项 -b 以Byte为单位显示内存的使用情况 -k 以K ...

  3. js邏輯

    js的邏輯對象可以用於將非邏輯對象轉換為邏輯 var a=new Boolean(); a為false的幾種情況,0,-0,null,false,“”,undefined,NAN

  4. 两个序列求前k大和

    ---恢复内容开始--- 没有题目,没有题意,这是学长提过的一个技巧,给你两个排好序的序列,每次可以各从中取一个,求前k大的和, 一个优先队列,先将a序列中最大的那个和b序列所有元素相加存进队列中,每 ...

  5. IT行业­——Linux

    现在是21世纪,是科学技术大力发展的一个时代,IT行业已经成为现在的一个非常热门的一个行业,许许多多的人都想要往IT方面发展,找IT方面相关的一个工作.因此,现在也出现了很多IT培训机构,比如培训Li ...

  6. wamp下php报错session_start(): open(d:/wamp/tmp\sess_ku776hvb06ko4lv9d11e7mnfj1, O_RDWR) failed: No such file or directory

    报错提示 session_start(): open(d:/wamp/tmp\sess_ku776hvb06ko4lv9d11e7mnfj1, O_RDWR) failed: No such file ...

  7. windows 系统无法安装

    1. 提示windows 无法安装到这个磁盘,选中的磁盘具有MBR分区表. Windows cannot be installed to this disk.the selected disk has ...

  8. 自学Linux Shell6.3-系统环境变量持久化

    点击返回 自学Linux命令行与Shell脚本之路 6.3-系统环境变量持久化 在你登录Linux系统启动一个bash shell时,默认情况下bash在几个文件中查找命令,这几个文件成为启动文件:b ...

  9. bzoj4336 骑士的旅行 (树链剖分+multiset)

    首先大概有一个树剖+树套树的做法,但我哪会写啊 然后发现k很小,如果用线段树记每个区间前k大的的话,可以O(k)地合并 而且一个点还有可能有好多个骑士,所以要用multiset维护一下 然后树剖就好啦 ...

  10. luogu1965 转圈游戏 (快速幂)

    求(m*10^k+x)%n即可 #include<cstdio> #include<cstring> #include<algorithm> #define LL ...