final 关键字小结笔记
修饰类
被final修饰的类不能被继承
,在final类中给任何方法添加final关键字是没有任何意义的。
final类型的类如何拓展?
组合实现
修饰方法
被final修饰的方法不能被子类重写
- private 方法是隐式的final,对private方法增添final关键字没什么意义。
- final方法是可以被重载的
修饰变量
并非所有的final修饰的字段都是编译期常量
static final : 一个既是static又是final 的字段只占据一段不能改变的存储空间,它必须在定义的时候进行赋值,否则编译器将不予通过。
Java 允许生成空白final
被声明为final但又没有给出定值的字段,但是必须在该字段被使用之前被赋值;
空白final:在构造器中进行赋值,保证声明为final的字段在被使用前赋值。
修饰参数(主要用于匿名内部类传递数据)
Java允许在参数列表中以声明的方式将参数指明为final,这意味这你无法在方法中更改参数引用所指向的对象。
final 重排序
final修饰基本数据类型
写final域重排序规则
- JMM禁止编译器把final域的写重排序到构造函数之外
- 编译器会在final域写之后,构造函数return之前,插入一个storestore屏障。这个屏障可以禁止处理器把final域的写重排序到构造函数之外。
读final域重排序规则
在一个线程中,初次读对象引用和初次读该对象包含的final域,JMM会禁止两个操作的重排序。处理器会在读final域操作的前面插入一个LoadLoad屏障。
final修饰引用数据类型
针对引用数据类型,final域写针对编译器和处理器重排序增加了这样的约束:在构造函数内对一个final修饰的对象的成员域的写入,与随后在构造函数之外把这个被构造的对象的引用赋给一个引用变量的两个操作是不能重排序的。
final使用
- 将指向对象的成员声明为 final 只能将该引用设为不可变的,而非所指的对象。
- 当声明一个 final 成员时,必须在构造函数退出前设置它的值。
final引用不能从构造函数中“溢出”
为什么?
byte b1=1;
byte b2=3;
byte b3=b1+b2;//当程序执行到这一行的时候会出错,因为b1、b2可以自动转换成int类型的变量,运算时java虚拟机对它进行了转换,结果导致把一个int赋值给byte-----出错
final byte b1=1;
final byte b2=3;
byte b3=b1+b2;//不会出错,相信你看了上面的解释就知道原因了。