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; // 错误
}
}
[size=1em][color=white !important][size=1em]?
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所引用的对象不
被修改。
|