一、final关键字
1.final修饰类,类不能被继承 2.final修饰方法,不能被子类重写 3.final修饰变量(成员变量、静态变量和局部变量),只能被赋值一次 4.final修饰的变量,变量的属性值是可以重新赋值的 5.final修饰的变量被赋值一次后就成了常量
二、常量
1.字面值常量,能够直接写出来的数据,例如100,3.14,‘a’,true,“abcd”,null(null不能被直接打印) 2.自定义常量,被final修饰的变量,被赋值一次就变成了常量,例如final int a = 20; final Student student = new Student(); 但student.age = 22;还是可以修改的,因为student指向的是student的内存地址,被final修饰后是不能变的,但age属性的地址没有被final修饰,所以是可变的
三、设置final变量的原理
3.1 代码示例
public class FinalLearning{
final int a = 20;
}
3.2 字节码
0 aload_0
1 invokespecial #1 <java/lang/Object.<init> : ()V>
4 aload_0
5 bipush 20
7 putfield #2 <com/FinalLearning.a : I>
<---写屏障
10 return
3.3 说明
1.int a = 20;是两个操作,首先给变量分配空间,初始值为0,然后才会赋值为20,如果其它线程在赋值20之前读到a为0,则变量的使用是不正确的 2.final会加写屏障 3.写屏障能让之前的指令不会被重排序到写屏障后面,写屏障之前的所有赋值操作在写屏障之后会被同步到主存,对其它线程可见
四、获取final变量的原理
1.类A使用类B的final属性时,较小的数据会复制到类A方法的方法栈,如果数值较大,会放入常量池中,不加final会从堆中访问,效率最低