Java之final修饰
final关键字用于修饰类,变量和函数,用于表示它修饰的类,函数和变量不可改变。
final成员变量
类Field:必须在静态初始化块中或声明该Field时指定初值。
实例Field:必须在非静态初始化块,声明该Field或构造器中指定初值。
已经初始化的实例Field不能再赋值。
public class Test{ final int a = 4; // 在声明时赋值 final int b; final static double c; final static double d = 4.5;// 在声明时赋值 final int e; {//非静态初始化块 b = 4; // final实例Field c = 5.5; // 发生错误,类Field不能在非静态初始化块中指定初值 } static{//静态初始化块 c = 5.5; // ok }}
final局部变量
在定义时没有指定默认值,则可以在后面代码中对该final变量赋初始值,但只能一次,不能重复赋值。
public void Test(){ final int a; a = 6; // 合法 a = 8; // 错误,只能一次,不能重复赋值}
final修饰基本类型变量和引用类型变量的区别
基本变量:被final修饰的基本变量,它的值不能被改变。
引用变量:final只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全
可以改变其内部的Field的值。
class AA{ int t = 222;}public class Test{ public static void main(String[] args){ AA a = new AA(); AA b = new AA(); final AA aa = a; // 合法 aa.t = 5; aa = b; // 错误 }}
final的宏替换
只要满足3个条件,这个final变量就不再是一个变量,而是一个宏替换
1.使用final修饰。
2.在定义该final变量时指定了初始值。
3.该初始值可以在编译时就被确定下来。
final int a = 5;System.out.println(a); // a不存在,只是替换成System.out.println(5);final int b = 6 * 8; // 如果被赋的表达式只是基本的算术表达式或字符串连接运算,没有访问 // 变量,调用方法,Java编译器同样会将这种final变量当成宏变量
final方法
final修饰的方法不可被重写
final类
final修饰的类不可被继承
自定义不可变类
创建自定义不可变类,可遵守以下规则:
1.使用prviate和final修饰符来修饰该类的Field。
2.提供带参数的构造器,用于根据传入参数来初始化里的Field。
3.仅为该类的Field提供getter函数,不要为其提供setter函数,因为普通方法无法修改final修饰的Field。
4.如有必要,重写Object类的hash和equals函数。
创建自定义不可变类时,如果包含其Field是可变的,则需要采取必要的措施来保护该Field所引用的对象不
被修改。