final原理

1. 设置 final 变量的原理

理解了 volatile 原理,再对比 final 的实现就比较简单了

public class TestFinal {
	 final int a = 20;
}

字节码

0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 20
7: putfield #2 // Field a:I
    <-- 写屏障
10: return

发现 final 变量的赋值也会通过 putfield 指令来完成,同样在这条指令之后也会加入写屏障,保证在其它线程读到它的值时不会出现为 0 的情况

写屏障可以保证两点:

  1. 可以保证写屏障之前的指令不会被重排序到写屏障后面去
  2. 保证写屏障之前的修改操作,赋值操作,在写屏障之后可以同步到主存,对其他线程可见

2. 获取 final 变量的原理

public class TestFinal {
    final static int A = 10;
    final static int B = Short.MAX_VALUE+1;

    final int a = 20;
    final int b = Integer.MAX_VALUE;

    final void test1() {
        final int c = 30;
        new Thread(()->{
            System.out.println(c);
        }).start();

        final int d = 30;
        class Task implements Runnable {

            @Override
            public void run() {
                System.out.println(d);
            }
        }
        new Thread(new Task()).start();
    }

}

class UseFinal1 {
    public void test() {
        System.out.println(TestFinal.A);
        System.out.println(TestFinal.B);
        System.out.println(new TestFinal().a);
        System.out.println(new TestFinal().b);
        new TestFinal().test1();
    }
}

class UseFinal2 {
    public void test() {
        System.out.println(TestFinal.A);
    }
}

从字节码中才能看出来,
在这个测试中,如果TestFinal中的A加了final,那么类UseFinal1中使用A的时候就发现,TestFinal直接把A复制了一份放在了UseFinal1的栈中,如果不加final,那么UseFinal1使用A的时候要调用GETSTATIC方法去获取。
同理TestFinal中的B,虽然是个很大的数,但是加了final,UseFinal1在使用的时候,发现是从常量池中取得(就是复制到常量池中了),要是不加final,UseFinal1使用的时候,还是要GETSTATIC。
在这里插入图片描述
这就是读取final变量时的优化。简单地说,其实就是相当于复制一份直接给用的那个人。

相关推荐

  1. final

    2024-04-29 23:24:04       50 阅读
  2. 精通并发【基础原理研究一】:Final

    2024-04-29 23:24:04       39 阅读
  3. finalfinallyfinalize区别

    2024-04-29 23:24:04       45 阅读
  4. final, finally, finalize的区别

    2024-04-29 23:24:04       49 阅读
  5. C#面:final ,finallyfinalize 的区别

    2024-04-29 23:24:04       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-29 23:24:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-29 23:24:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-29 23:24:04       82 阅读
  4. Python语言-面向对象

    2024-04-29 23:24:04       91 阅读

热门阅读

  1. 采购管理软件:如何高效跟踪采购订单?

    2024-04-29 23:24:04       30 阅读
  2. 三大语音机器人:如何提升销售效率

    2024-04-29 23:24:04       35 阅读
  3. windows ubuntu:sed,awk,grep篇:4.执行 sed

    2024-04-29 23:24:04       34 阅读
  4. 机器人技术概述_3.机器人的分类

    2024-04-29 23:24:04       25 阅读
  5. 机器学习——构建决策树

    2024-04-29 23:24:04       36 阅读
  6. git常用命令

    2024-04-29 23:24:04       27 阅读
  7. 面试 Python 基础八股文十问十答第七期

    2024-04-29 23:24:04       35 阅读
  8. docker如何查看对外暴露接口

    2024-04-29 23:24:04       32 阅读
  9. Linux的docker基础知识

    2024-04-29 23:24:04       33 阅读
  10. linux切换工作目录

    2024-04-29 23:24:04       32 阅读