深入理解java final

对于final域,编译器和处理器要遵守两个重排序规则:

1: 在构造函数内对一个final域的写入,与随后把这个构造对像的引用赋值给变量,不能重排序。(禁止把final域的写重排序到构造函数外,会在final域的写之后,构造函数return之前插入一个storestore屏障)

2: 

finalExample  obj= new FinalExample ()。这行代码包含两个步骤:

1: 构造一个FinalExample类型的对象。

2: 把这个对象的引用赋值给引用变量obj

假设线程b读取对象引用和读对象成员域之间没有重排序,


上图中,写普通域的操作被编译器重排序到构造函数之外,读线程b错误的读取了普通变量i初始化之前的值,但final域限定在构造函数之内。final域的重排序规则可以确保在对象引用为任意线程可见之前,final域已经被初始化过了。

在一个线程中,初次读对象引用和初次读该对象包含的final域,jmm禁止处理器重排序这两个操作,编译器会在读final域操作的前面插入一个loadload屏障。初次读对象引用和初次读该对象包含的final域,这两个操作之间存在间接依赖关系。由于编译器遵守间接依赖关系,编译器不会重排序这两个操作,大多数处理器也会遵守间接依赖,大多数处理器也不会重排序这两个操作。但有的处理器会,这个规则就是专门这种处理器的。


上图中,读对象的普通域操作被处理器重排序到读对象引用之前,该域还没有被线程a写入,这是一个错误的读取操作。而读final域会将其限定在读对象的引用之后。

#### JAVA局部变量加final修饰的好处

一般来说有以下这几种用法:

1、for循环中,使用局变量来保存循环数次,并用final修饰,而非直接用getCount()、getSize()、lenght等

2、需要访问集合中的某个对象时,使用局部变量来引用,并用final修饰,而非直接引用

3、需要访问外部某个对象时,使用局部变量来引用,并用final修饰,而非直接引用

个人理解的好处有:

1、访问局部变量要比访问成员变量要快

2、访问局部变量要比每次调用方法去获取对象要快

3、使用final修饰可以避免变量被重新赋值(引用赋值)


先把成员或静态变量读到局部变量里保持一定程度的一致性,例如:在同一个方法里连续两次访问静态变量A.x可能会得到不一样的值,因为可能会有并发读写;但如果先有final int x = A.x然后连续两次访问局部变量x的话,那读到的值肯定会是一样的。这种做法的好处通常在有数据竞态但略微不同步没什么问题的场景下,例如说有损计数器之类的。


> Accessing a local variable is faster than accessing a field.  It's best to keep field accesses out of performance-critical inner loops when possible.  (Profile first, of course, to see if it matters.)  In theory the JVM could "inline" the field to a local variable automatically under the right conditions, but don't count on it.

> A final local variable is not any different from a normal local variable at runtime.  The "final" keyword on a local variable expresses a constraint on the source code (that it is assigned to once) which the compiler can easily check.

> Final *fields* do allow additional optimizations, and static final fields with primitive values (as in "public static final int MY_CONSTANT = 3") are treated as compile-time constants and inlined.


> When talking about final local variables keep in mind that using the keyword final will help the compiler optimize the code statically, which may in the end result in faster code. For example, the final Strings a + b in the example below are concatenated statically (at compile time).

```

public class FinalTest {

    public static final int N_ITERATIONS = 1000000;

    public static String testFinal() {

        final String a = "a";

        final String b = "b";

        return a + b;

    }

    public static String testNonFinal() {

        String a = "a";

        String b = "b";

        return a + b;

    }

    public static void main(String[] args) {

        long tStart, tElapsed;

        tStart = System.currentTimeMillis();

        for (int i = 0; i < N_ITERATIONS; i++)

            testFinal();

        tElapsed = System.currentTimeMillis() - tStart;

        System.out.println("Method with finals took " + tElapsed + " ms");

        tStart = System.currentTimeMillis();

        for (int i = 0; i < N_ITERATIONS; i++)

            testNonFinal();

        tElapsed = System.currentTimeMillis() - tStart;

        System.out.println("Method without finals took " + tElapsed + " ms");

    }

}

```

```

Method with finals took 5 ms

Method without finals took 273 ms

```

So how much is the actual performance improvement? I don't dare say. In most cases probably marginal (~270 nanoseconds in this synthetic test because the string concatenation is avoided altogether - a rare case), but in highly optimized utility code it might be a factor. In any case the answer to the original question is yes, it might improve performance, but marginally at best.

Compile-time benefits aside, I could not find any evidence that the use of the keyword final has any measurable effect on performance.

https://stackoverflow.com/questions/4279420/does-use-of-final-keyword-in-java-improve-the-performance

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

推荐阅读更多精彩内容