Java中被final修饰的变量与普通变量有何区别?被final修饰的变量不可更改、被final修饰的方法不可重写是怎样做到的?带着疑问我们一点点拨开云雾。

一、final的内存定义及规则

对于final关键字,编译器、处理器从读写两个角度限制了其使用规则:

  • 对于一个类的final修饰的变量,如果在定义是不指定初始值,那么在构造函数中必须进行初始化,在构造函数中进行final域的写入时,随后将构造后的对象引用赋值给另外一个引用变量,它们之间不能进行重排序的发生。
  • 在读一个包含final关键字的对象引用和读这个引用的包含的final修饰的变量时,这两个操作间不能发生重排序。

下面通过一段代码分析一下具体场景:

public 

这里先假设A线程执行finalWriter方法,B线程执行finalRead()方法,通过上述对于final的规则描述我们分析一下finalWriter方法的执行流程:

  1. 构造一个FinalTest对象
  2. 将构造后的对象引用进行赋值

对于final修饰的变量进行赋值操作时的重排序规则如下:

1、Java内存模型禁止将对final关键字修饰的变量进行写操作重排序到构造函数之外。
2、编译器会在写之后,构造函数return之前插入StoreStore屏障,这个屏障确保编译器不会把final变量写操作重排序到构造函数之外。

下面假定一种重排序的场景如下图所示:

final域的写流程

上图的场景情况为变量i为普通变量,在进行赋值时发生了重排序(由于这时候有可能构造函数还未完成),在构造函数结束后,才进行了赋值,线程B读取到的i的值为赋值前的初始值0,而对于final修饰的变量j由于禁止重排序,在构造函数return前需要进行赋值,限定到了构造函数内,读取到的变量j为正确的值。

然后再分析一下执行finalRead()方法的流程:

  1. 读引用变量Obj将其赋值给object变量。
  2. 读引用的普通变量i。
  3. 读引用的final修饰的变量j

对于final修饰的读操作重排序规则:

在一个线程中首次读对象的引用和首次读该对象包含的final修饰的变量,Java内存模型禁止重排序(也就是说在读取一个final修饰的变量前,一定是先获取该变量对应的引用),主要原理就是在读取final修饰的变量前插入LoadLoad屏障。

假设上述情况,线程A正常执行,变量i没有发生重排序的情况,而对于线程B读取变量i和读对象的引用发生了重排序,如下图所示

读对象的普通变量i时处理器发生了重排序,读变量在读对象的引用之前发生,这时候变量还未开始进行赋值,而对于final修饰的变量j来说,由于其遵循重排序规则(读变量首先要读变量对应的对象引用),所以读取的值是正确的。

除了上述两种场景之外,假设在构造函数内使用this关键字将当前对象赋值给成员变量(逸出),如下代码所示:

public 

这时候同样有两个线程,一个线程执行finalWriter,另外一个执行finaRead,也有可能会出现被final修饰的变量j没有进行赋值的情况。

参考《Java并发编程的艺术》

扫码关注“聊点源码”获取更多资讯

final关键字_深入分析Java中的final关键字相关推荐

  1. java final 类_在Java中,final修饰的类有什么特点

    展开全部 关于Java中的32313133353236313431303231363533e4b893e5b19e31333264663736final(2010-09-09 14:19:48)转载▼ ...

  2. 在 java 中 关于final 关键字_在Java中,关于final关键字的说法正确的是

    摘要: 人类统地著:中字的正确美育也是确系部明文化论述第一的论史上,著"美级在育"部资论论第一的理产阶方面.说法中字的正确信方轨道工B工C工天线交通接收.全半双的通.单车载采用式( ...

  3. java final 初始化_在Java中,可以从构造函数助手中初始化final字段吗?

    我有一个最终的非静态成员: private final HashMap myMap; 我想使用构造函数调用的方法对其进行初始化. 由于myMap是最终版本,因此我的" helper" ...

  4. java final 意思_在java中一个类被声明为final类型,表示的意思是()。

    案例分析一:假定CPU的主频是500MHz.硬盘采用DMA方式进行数据传送,其数据传输率为4MB/s, 每次DMA传输的数据量为8KB, 要求没有任何数据传输被错过. 如果CPU在DMA初始化设置和启 ...

  5. [5] Java中的static关键字

    Java中的static关键字 文章目录 Java中的static关键字 static的基本概念 static修饰类中的成员 static修饰主类中的方法 static修饰类中的方法 static修饰 ...

  6. java final 修改_“无法改变的设计”——浅谈Java中的final关键字

    在Java中,final关键字可以用来修饰类.变量(包括成员变量和局部变量).方法,下面从这三个方面分别说明. final方法 当一个方法被final修饰时,表明这个方法不能被子类重写. 下面程序试图 ...

  7. java final 变量 好处_深入理解Java中的final关键字

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  8. java中final是啥意思_(转)深入理解Java中的final关键字

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  9. 浅谈Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

最新文章

  1. 喜大普奔!GitHub官方文档推出中文版
  2. C语言打印1000以内的完数
  3. 复杂科学2021年度精选:从诺贝尔奖到未来科学
  4. 利用mysql的预编译机制_SQL注入笔记记录+MySQL的事务隔离级别
  5. SQL、LINQ、Lambda 三种用法
  6. GroupBox控件
  7. 到现在还说房价不可能跌的都是些什么样的人?
  8. 千万级用户直播APP——服务端结构设计和思考
  9. 洛谷 P1168 中位数 堆
  10. 国内29家视觉企业及最新动态一览
  11. C 语言 运算符 全网最全整理
  12. PBR 六 材质参数
  13. 键盘侠小心了!微博或将推出“杠精”示众功能
  14. opencv面试知识点
  15. 计算机论文的致谢部分写什么,毕业论文致谢部分怎么写
  16. 网页制作之JavaScript篇
  17. 史上最全最牛的C++整人代码
  18. 【实用软件】流氓软件清理器-SoftCnKiller
  19. 谷歌 不支持 activeX插件
  20. 拼多多开店怎么提高点击率?天创速盈提出应对措施

热门文章

  1. VS2010中使用sprintf出现warning C4997: 'sprintf': This function or variable may be unsafe.
  2. Autofac在Asp.net MVC中在 Areas拆分到不同DLL下的注入失败问题
  3. 精通ASP.NET MVC ——辅助器方法
  4. C#中 out、ref、params 修饰符使用方法
  5. 湖北工业大学计算机专硕学费,2019年湖北工业大学硕士研究生学费奖助政策
  6. mysql 回滚失败_Mysql非事务表回滚失败的现象
  7. python中csv模块是自带的吗_python csv模块 Python的CSV模块,怎么新建为添加模式
  8. button 样式_缩减 SCSS 50%样式代码的 14 条实战经验
  9. 织梦html权限设置,详细的Dede织梦目录权限安全设置教程
  10. java中的成员变量和局部变量的区别_java中成员变量与局部变量区别分析