河北网站设计公司,flash教程网站首页,中高端网站建设,做酱菜网站Java中被final修饰的变量与普通变量有何区别#xff1f;被final修饰的变量不可更改、被final修饰的方法不可重写是怎样做到的#xff1f;带着疑问我们一点点拨开云雾。一、final的内存定义及规则对于final关键字#xff0c;编译器、处理器从读写两个角度限制了其使用规则被final修饰的变量不可更改、被final修饰的方法不可重写是怎样做到的带着疑问我们一点点拨开云雾。一、final的内存定义及规则对于final关键字编译器、处理器从读写两个角度限制了其使用规则对于一个类的final修饰的变量如果在定义是不指定初始值那么在构造函数中必须进行初始化在构造函数中进行final域的写入时随后将构造后的对象引用赋值给另外一个引用变量它们之间不能进行重排序的发生。在读一个包含final关键字的对象引用和读这个引用的包含的final修饰的变量时这两个操作间不能发生重排序。下面通过一段代码分析一下具体场景public 这里先假设A线程执行finalWriter方法B线程执行finalRead()方法通过上述对于final的规则描述我们分析一下finalWriter方法的执行流程构造一个FinalTest对象将构造后的对象引用进行赋值对于final修饰的变量进行赋值操作时的重排序规则如下1、Java内存模型禁止将对final关键字修饰的变量进行写操作重排序到构造函数之外。2、编译器会在写之后构造函数return之前插入StoreStore屏障这个屏障确保编译器不会把final变量写操作重排序到构造函数之外。下面假定一种重排序的场景如下图所示final域的写流程上图的场景情况为变量i为普通变量在进行赋值时发生了重排序由于这时候有可能构造函数还未完成在构造函数结束后才进行了赋值线程B读取到的i的值为赋值前的初始值0而对于final修饰的变量j由于禁止重排序在构造函数return前需要进行赋值限定到了构造函数内读取到的变量j为正确的值。然后再分析一下执行finalRead()方法的流程读引用变量Obj将其赋值给object变量。读引用的普通变量i。读引用的final修饰的变量j对于final修饰的读操作重排序规则在一个线程中首次读对象的引用和首次读该对象包含的final修饰的变量Java内存模型禁止重排序也就是说在读取一个final修饰的变量前一定是先获取该变量对应的引用主要原理就是在读取final修饰的变量前插入LoadLoad屏障。假设上述情况线程A正常执行变量i没有发生重排序的情况而对于线程B读取变量i和读对象的引用发生了重排序如下图所示读对象的普通变量i时处理器发生了重排序读变量在读对象的引用之前发生这时候变量还未开始进行赋值而对于final修饰的变量j来说由于其遵循重排序规则读变量首先要读变量对应的对象引用所以读取的值是正确的。除了上述两种场景之外假设在构造函数内使用this关键字将当前对象赋值给成员变量逸出如下代码所示public 这时候同样有两个线程一个线程执行finalWriter另外一个执行finaRead也有可能会出现被final修饰的变量j没有进行赋值的情况。参考《Java并发编程的艺术》扫码关注“聊点源码”获取更多资讯