final关键字

1.final的具体使用场景

final能够修改变量,方法和类。

1.1修饰变量

在java中变量可以分为成员变量和局部变量

1.1.1修饰成员变量

每个类中的成员变量可以分为类变量(static修饰的变量)和实例变量。这两种变量赋初值的时间是不同的。类变量可以在声明的时候静态代码块中赋初值。而实例变量可以在声明的时候赋初值,在非静态初始化块中以及构造器中赋初值。当final变量未初始化时系统不会进行隐式初始化,会报错。

1.1.2修饰局部变量

final局部变量由程序员进行显示初始化,如果final局部变量已经进行了初始化,则后面就不能再次进行更改,如果final变量未进行初始化,可以进行赋值,当且仅有一次赋值,一旦赋值之后再次赋值就会报错。
final基本数据类型final引用数据类型
如果final修饰的是一个基本数据类型,那么一旦初始化,就不能更改。
如果final修饰的是引用数据类型,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不会改变,即一直引用这个对象,但是这个对象的属性可以改变
宏变量
利用final变量的不可更改性,在满足以下三个条件时,变量就成为一个宏变量,即常量
1.利用final修饰符修饰。
2.在定义该fanal变量时就指定了初值。
3.该初始化值在编译时就能够唯一确定。

1.2修饰方法

重写?(不能)

当父类的方法被final修饰的时候,子类不能重写父类的该方法,比如Object中,getClass方法就是final,我们不能重写该方法,但是hashCode方法就不是final,我们就可以重写。

重载?(能)

被final修饰的方法是可以重载的。

1.3修饰类

当一个类被final修饰时,表明该类是不能被子类继承的。

2.多线程中的final

上面我们聊的final使用,应该属于Java基础层面的,当理解这些后我们就真的算是掌握了final吗?有考虑过final在多线程并发的情况吗?在java内存模型中我们知道java内存模型为了能让处理器和编译器底层发挥他们的最大优势,对底层的约束就很少,也就是说针对底层来说java内存模型就是一弱内存数据模型。同时,处理器和编译为了性能优化会对指令序列有编译器和处理器重排序。那么,在多线程情况下,final会进行怎样的重排序?会导致线程安全的问题吗?下面,就来看看final的重排序。

2.1final域重排序规则

2.1.1final域为基本数据类型

public class FinalDemo {
    private int a;  //普通域
    private final int b; //final域
    private static FinalDemo finalDemo;

    public FinalDemo() {
        a = 1; // 1. 写普通域
        b = 2; // 2. 写final域
    }

    public static void writer() {
        finalDemo = new FinalDemo();
    }

    public static void reader() {
        FinalDemo demo = finalDemo; // 3.读对象引用
        int a = demo.a;    //4.读普通域
        int b = demo.b;    //5.读final域
    }
}

假设线程A正在执行writer方法,线程B执行reader方法。

写final域重排序规则

禁止对final域的写重排序到构造函数之外,这个规则的实现主要包括两个方面:
1.JMM禁止编译器把final域的写重排序到构造函数之外。
2.编译器会在final域写之后,构造函数return之前,插入一个storestore内存屏障。这个内存屏障可以禁止处理器把final域写重排序到构造函数之外。
因为a和b没有数据依赖性,普通变量a可能被重排序到构造函数之外,线程B就有可能读到的是普通变量a没有初始化之前的值。而final域变量b,根据重排序规则,会禁止final修饰的变量重排序到构造函数之外,所以线程B能够正确读到b的值。

读final域重排序规则

在一个线程中,初次读对象引用和初次读该对象包含的包含的final域,JMM会禁止这两个操作的重排序
可以确保在读一个对象的final域之前,一定会先读包含这个final域对象的引用

2.1.2 final域为引用数据类型

对final修饰的对象的成员域写操作

对final修饰的变量的成员域读操作

在构造函数内对一个final修饰的对象的成员域的写入,与随后在构造函数之外把这个被构造的对象的引用赋给一个引用变量,这两个操作是不能被重排序的
示例代码:

public class FinalReferenceDemo {
    final int[] arrays;
    private FinalReferenceDemo finalReferenceDemo;

    public FinalReferenceDemo() {
        arrays = new int[1];  //1
        arrays[0] = 1;        //2
    }

    public void writerOne() {
        finalReferenceDemo = new FinalReferenceDemo(); //3
    }

    public void writerTwo() {
        arrays[0] = 2;  //4
    }

    public void reader() {
        if (finalReferenceDemo != null) {  //5
            int temp = finalReferenceDemo.arrays[0];  //6
        }
    }
}

由于对final域的写禁止重排序到构造函数之外,因此1和3不能重排序
由于一个final域的引用对象的成员域写入不能与随后将这个被构造出来的对象赋给引用变量重排序,因此2和3不能重排序。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,333评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,812评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,016评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,293评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,650评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,788评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,003评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,741评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,462评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,681评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,168评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,528评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,169评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,119评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,846评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,719评论 2 274

推荐阅读更多精彩内容

  • 概念 final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。 一旦你将引用声明作fin...
    编码前线阅读 2,439评论 2 3
  • 多线程之 Final变量 详解 原文: http://www.tuicool.com/articles/2Yjmq...
    朦胧蜜桃阅读 1,355评论 0 2
  • final是Java中的一个关键字,final可用于修饰类、方法、参数和变量(包括实例变量和类变量)。 final...
    zhong0316阅读 1,349评论 4 4
  • 从不吝啬对别人的关心问候,因为我觉得就算不在身边,就算没有时常联系,但只要察觉他状态不好时,我的一通电话也会让他温...
    jkqg阅读 168评论 3 0
  • 很多时候,你的不经意的关心都可以让我泪流满面,很多时候,宁愿你可以冷漠一点无情一点,这样才不会心存幻想,这样才可以...
    瑾瑜无瑕阅读 178评论 0 0