提交 28421349 authored 作者: 邓砥奕's avatar 邓砥奕

第一次添加笔记

上级 c44be931
## Lambda和匿名内部类
#### 一、引用外部方法局部变量
Java8之前Lambda和匿名内部类引用外部局部变量必须声明为final类型,Java8之后引用的局部变量必须为final或effectively final.如果该局部变量在定义赋值后没有被修改,则认为该变量为effectively final类型,如果被赋值或修改则无法通过编译。因此在引用外部局部变量时,不能进行修改。
#### 二、为什么必须为final或effectively final
1.由于Lambda和匿名内部类无法直接访问外部局部变量,因此只能通过它们的构造方法将需要引用的局部变量传入进去。通过构造方法传递的只是局部变量的一个拷贝,因此当外部或者内部类修改这个变量时,对方都不知道该变量的修改。为了保证变量的安全,所以在Java中直接不允许修改引用的局部变量,编译时该变量必须为final或者effectively final类型。
2.局部变量和内部类对象的生命周期不同。当调用该方法时,该方法中的局部变量在栈中被创建,可能该方法调用结束并且释放了栈中的变量,但是内部类却还没有执行完,此时就找不到该局部变量了。为了保证变量的安全访问,内部类会自动通过构造函数的参数创建一个final类型的拷贝值。由于是拷贝值,因此一但一方修改了局部变量的值会导致另外一方对该变量的更改不可见,从而出现问题。
3.并发的安全性问题。当多个线程并发执行Lambda或匿名内部类中的代码时,不能保证外部成员变量的原子性,从而可能导致变量值的安全性问题。当引用自由变量时,考虑并发的安全性,也必须为final或effectively final。
#### 三、修改变量的一些方法
1.定义为内部类局部变量
2.定义为外部类的成员变量:成员变量存储在堆上,可以正常访问。
3.定义为Atomic原子类型:保证了变量的可见性和原子性。
4.定义为数组、list:数组和list的地址不会发生改变,可以修改数组和list中的值,但是并发时不能保证安全性。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论