https://pdai.tech/md/java/thread/java-thread-x-key-final.html
修饰类
final类不可继承
对应jdk源码
final与JVM 第 6 章 类文件结构 访问标志final
类加载总结文——源码
我们都知道一个类被类加载之后会生成一个对应的Class对象,也就是JVM中的Klass实例(instanceKlass),在填充该实例属性时会去验证是否有父类访问权限。如下:
check_super_class_access
如果父类是final类型,不能继承。
final类方法默认为final方法
和check_super_class_access一样,check_final_method_override,如果有重写父类final方法,抛出异常。
修饰方法
不能重写,可以重载
static final 必须在定义的时候进行赋值
一个既是static又是final 的字段只占据一段不能改变的存储空间,它必须在定义的时候进行赋值,否则编译器将不予通过。
修饰变量
变量一旦被赋值,就不可以更改它的值。因为字段具有标识符信息,它会将final信息记录ACC_FINAL,表示一个常量值,放入常量池。
可以看到引用字段会经过 <clinit> 方法, helloworld1直接作为常量
修饰成员变量
如果final修饰的是成员变量,可以在非静态初始化块中指定初始值或者声明该类变量时指定初始值。
修饰静态变量
如果final修饰的是静态变量,只能在静态初始块中指定初始值或者声明该类变量时指定初始值。
修饰局部变量
我们知道局部变量和以上两个变量不同,只有在方法压栈之后才会处理,所以没有初始化一说,在使用final遍历修饰局部变量时,可以指定默认值,也可以不指定,但只能初始一次、使用前赋值的规则不变
修饰基本类型数据和引用类型数据
基本类型数据一旦初始化之后便不能更改
引用类型 final的是引用关系,而不是引用的对象。
也就是说引用的对象值可以改变,但是这种引用关系不能改变。
拓展
final实现可见性(有条件的)
而final关键字的可见性是指:被final修饰的字段在构造器中一旦被初始化完
成,并且构造器没有把“this”的引用传递出去(this引用逃逸是一件很危险的事情,其他线程有可能通过这个引用访问到“初始化了一半”的对象),那么在其他线程中就能看见final字段的值。如代码清单12-7所示,变量i与j都具备可见性,它们无须同步就能被其他线程正确访问。
https://www.infoq.cn/article/java-memory-model-6 更多关于final重排序