Final【Java】
简介
Final是Java的关键字,Final可以用于修饰类、方法、变量(包括成员变量和局部变量)。
Java类使用Final修饰之后,该类不可以再被继承,这样做通常处于安全考虑。
使用final方法的原因有两个。
第一个原因是把方法锁定,以防任何继承类修改它的含义;
第二个原因是出于效率考虑,早期的 Java 实现版本中,会将 final 方法转为内嵌调用,内嵌调用在方法体较小时候会因为减少了方法调用成本而得到一定的效率提升。最近的Java版本中,已经不需要使用final方法进行这些优化。
Java类的 private 方法模式是Final方法。
被Final修饰的Java类中所有的成员方法默认都是Final方法。
Final修饰变量时候的语义是该变量的值不可被修改。
原理
内存屏障
通过 Final 关键词修饰的变量,必须初始化之后才可以使用。
为了避免重排序,Final 的变量在构造方法中加入了内存屏障。构造函数结束之前 Final 变量增加了StoreStore内存屏障,在初次读取 final 变量之前加上了 LoadLoad 内存屏障。
加入内存屏障可以避免未被初始化的变量被其他线程使用。
语法检验
Java类的使用需要经历加载,链接,初始化之后才能使用。
在链接阶段又分为校验、准备以及解析的过程。
在校验阶段Java 虚拟机会对字节码进行语义检查,对于不符合JVM规范的指令,Java虚拟机会返回校验失败的错误。
被定义为Final的类或者成员方法禁止被继承或者重写会在这个阶段进行校验。
使用
Final类
当final修饰类的时候表明该类不能被继承,并且类中所有的属性和方法都默认是final类型,如String,Integer等包装类均为final类。
Final类不能被继承,可以有效的保护Java中的类的安全性。
Final方法
被final修饰的方法不可被重写。它可以防止任何继承类修改方法的意义和实现,使用final修饰方法可以通过内联机制将方法调用转为合并成大的方法体,从而提升执行效率。
Final变量
java 的匿名内部类参数引用必须是 final 的。
Java的参数传递无论是基本类型还是对象,传递的都是值或者引用的拷贝,当基本类型作为参数传递时,传递的是值的拷贝,当对象作为参数传递时,传递的是对象的引用的拷贝,所以这些拷贝的值发生变化之后不会影响到调用方的变量的值。
匿名内部类本质上是一种闭包,闭包需要更改外部的变量,为了可以影响外部的变量,所以需要这个引用的对象可以发生内容的变化,但是值不能发生变化,所以需要声明为 final 的。