参考:
https://www.jianshu.com/p/ade870238d18

最近在学习多线程的知识,感觉自己超级无知,写了这么久代码,我连匿名内部类都搞不太懂哈哈,但是我愿意学,哪怕从头开始。

首先贴一下我学习的代码

package cn.ctwom.projone;import java.util.ArrayList;
import java.util.List;/*** @title:* @description:* @author: jiangman* @time: 2018/12/29 10:13*/
public class WaitAndNotify {private volatile static List list = new ArrayList();public void add(){list.add("a");}public int size(){return list.size();}public static void main(String[] args){//final修饰的变量是不可以修改的,所以相当于是常量。//如下的两个对象变量一个是为了调用其中的方法而存在,一个是为了加锁而存在。//所以不存在修改其本身的问题,那么既然不会修改那为什么还要加呢?//这里之所以加上了final,是为了防止其他的地方会修改这两个对象,出现线程调度问题。//比如:不加final如果对这两个对象进行重复赋值的话,代码是会在编译期就发现报错的,会进行提示,所以还是得要加的。(当然不重复赋值是没问题的)//报错信息:Variable 'waitAndNotify' is accessed from within inner class, needs to be final or effectively final//inner class:内部类 说的是new Runnable实现的这个匿名内部类final WaitAndNotify waitAndNotify = new WaitAndNotify();final Object lock = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {try {synchronized (lock){for(int i = 0; i < 10; i++){waitAndNotify.add();System.out.println("当前线程:"+Thread.currentThread().getName()+"添加了一个元素");Thread.sleep(500);if(waitAndNotify.size()==5){System.out.println("已经发出通知...");lock.notify();lock.wait();}}}} catch (InterruptedException e) {e.printStackTrace();}}},"t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (lock){if(waitAndNotify.size()!=5){try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("当前线程:"+Thread.currentThread().getName()+"收到通知线程");lock.notify();throw new RuntimeException();}}},"t2");t2.start();t1.start();}
}

31行和33行 我都用了final关键字,如果还是当前这些代码,其实去掉了这两个final关键字编译也是不会报错的。因为没有对变量重新赋值,那么jdk1.8就默认他是一个常量了,如果你在其他地方给它重新赋值一下,那么他就会报红:

Variable 'waitAndNotify' is accessed from within inner class, needs to be final or effectively final

当然这只针对jdk1.8哈,8之前的不加final编译是肯定不会通过的,非要你加上了final它才安心。
那么final 和effectively final到底啥意思啥区别呢?
具体的如下,是我参考的最上面链接的博友找到的解释,反正我看懂了嘿嘿。

总之,总结下来就是说:
针对于jdk1.8,对于一个变量,如果没有给它加final修饰,而且没有对它的二次赋值,那么这个变量就是effectively final(有效的不会变的),如果加了final那肯定是不会变了哈。就是这个意思。

在学习局部内部类(local inner class)时,遇到了effectively final 的说法。一时不知所云,就google了一下。下面是stackoverflow上的解答,看完,顿时豁然开朗,记载一下,供后来者查阅。
Difference between final and effectively final
其中一位回答,感觉很好:
… starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
For example, suppose that the variable numberLength is not declared final, and you add the marked assignment statement in the PhoneNumber constructor:
public class OutterClass {
int numberLength; // <== not final
class PhoneNumber {
PhoneNumber(String phoneNumber) {
numberLength = 7; // <== assignment to numberLength
String currentNumber = phoneNumber.replaceAll(
regularExpression, “”);
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}

}

}
Because of this assignment statement, the variable numberLength is not effectively final anymore. As a result, the Java compiler generates an error message similar to “local variables referenced from an inner class must be final or effectively final” where the inner class PhoneNumber tries to access the numberLength variable:
如果你给变量numberLength 又重新赋值了,则numberLength就不再是effectively final。java 编译出错 “local variables referenced from an inner class must be final or effectively final”
作者:ae12
链接:https://www.jianshu.com/p/ade870238d18
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

final 和effectively final区别相关推荐

  1. Java8新特性:等同 final 效果(Effectively Final)

    闭包 Effectively Final 示例 闭包 闭包就是能够读取函数作用域之外的变量的函数. 考虑一个返回复杂的 lambda 的高阶函数,使用了函数作用域之外的变量,返回该函数会发生什么? j ...

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

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

  3. 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 原因:在 ...

  4. java中的final关键字和effectively final

    我们在给lamda传参数时,可能会出现如下情况: Variable used in lambda expression should be final or effectively final 一般情 ...

  5. java增加final,Java8增加功能--Effectively final 功能

    java8新增了很多功能,可以大大简化代码,这个系列将会一一辅助代码加以介绍. 局部内部类和匿名内部类访问的局部变量必须由final修饰,java8开始,可以不加final修饰符,由系统默认添加.ja ...

  6. 1.20 Java8新特性:Effectively final

    Java 中局部内部类和匿名内部类访问的局部变量必须由 final 修饰,以保证内部类和外部类的数据一致性.但从 Java 8 开始,我们可以不加 final 修饰符,由系统默认添加,当然这在 Jav ...

  7. final,finally,finaliz的区别(Java)

    final,finally,finaliz的区别(Java) final-修饰符(关键字) 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 a ...

  8. java中static、final 和 static final之间的区别

    java中static.final 和 static final之间的区别 static可以修饰:全局属性,方法,代码块,内部类(静态内部类或嵌套内部类) 由于静态属性和方法是属于该类的所有对象的,所 ...

  9. java 8新特性之effectively final

    我们平时使用内部类时,如果需要使用外部的变量,只能通过final关键字来修饰该变量,在java8中,有了新的处理方式,如下: 针对于jdk1.8,对于一个变量,如果没有给它加final修饰,而且没有对 ...

  10. final 、finally的区别

    final .finally 开发工具与关键技术:工具:myeclipse 技术: final .finally 作者:吴东梅 撰写时间:2019-05-11 final和finally单词书写相似, ...

最新文章

  1. 针对JavaScript的常用事件、对象捕获和使用技巧
  2. Delphi 调用webservice接口
  3. 迷茫的未来,我们需要做些什么呢?
  4. C#以post方式调用struts rest-plugin service的问题
  5. 大数据让人们得到更加细致和人性化的服务
  6. C/C++面试题精选
  7. 关于SDIO接口的wifi和通用SD卡的一些记录
  8. iOS逆向工程——非越狱调试
  9. ecshop最全去版权
  10. XCode编译器里有鬼 – XCodeGhost样本分析
  11. 阿里菜鸟JAVA实习生一面面试题
  12. X86与X64之间的区别
  13. STM32F103_study52_The punctual atoms(STM32 The running light experiment )
  14. 多路视频直播播放器系统框架
  15. 荆棘遍地,鲜花满开(随笔二)
  16. 人工智能会代替人工翻译?知行翻译:这是不可能地!
  17. web前端面试题— 简答题
  18. 编程利器!有道词典命令行快速翻译
  19. 【论文阅读记录】孪生网络(Siamese network)
  20. linux入门学习(3权限管理)

热门文章

  1. no interpreter
  2. 如何在 oracle 集群环境下修改私网信息 (文档 ID 2103317.1)
  3. Spring乱码问题解决
  4. 阴阳师服务器维护6,《阴阳师》手游6月10日维护更新公告
  5. QT界面怎么让控件跟随窗口大小变化
  6. centos ffmpeg 加水印
  7. exec函数用法总结
  8. Windows 下使用 TFTPD32+HTTP PXE引导安装linux
  9. iOS 图片引起的崩溃
  10. SQL 的各种 join 用法