final修饰变量
- 成员变量
- 类变量(static修饰的变量)
赋初值:
- 声明变量的时候直接赋初值
- 静态代码块中赋初值
- 实例变量
赋初值:
- 声明变量的时候给实例变量赋初值
- 非静态初始化块中赋初值
- 构造器中赋初值
- 局部变量
赋初值:
显式初始化,已经进行了初始化则后面就不能再次进行更改,如果final变量未进行初始化,可以进行赋值,当且仅有一次赋值,一旦赋值之后再次赋值就会出错
final基本数据类型 VS final引用数据类型
- 当final修饰基本数据类型变量时,不能对基本数据类型变量重新赋值,因此基本数据类型变量不能被改变。
- 而对于引用类型变量而言,它仅仅保存的是一个引用,final只保证这个引用类型变量所引用的地址不会发生改变,即一直引用这个对象,但这个对象属性是可以改变的。
宏变量:利用final变量的不可更改性,在满足一下三个条件时,该变量就会成为一个“宏变量”,即是一个常量。
- 使用final修饰符修饰;
- 在定义该final变量时就指定了初始值;
- 该初始值在编译时就能够唯一指定。
重写?
被final修饰的方法不能够被子类所重写。
public class FinalExampleParent { public final void test() { } }
重载?
1. 父类的final方法是不能够被子类重写的
2. final方法是可以被重载的
public class FinalExampleParent { public final void test() { } public final void test(String str) { } }
类
当一个类被final修饰时,表名该类是不能被子类继承的。子类继承往往可以重写父类的方法和改变父类属性,会带来一定的安全隐患,因此,当一个类不希望被继承时就可以使用final修饰。还是来写一个小例子:
public final class FinalExampleParent {
public final void test() {
}
}
父类会被final修饰,当子类继承该父类的时候,就会报错,如下图:
final经常会被用作不变类上,利用final的不可更改性。我们先来看看什么是不变类。
不变类
不变类的意思是创建该类的实例后,该实例的实例变量是不可改变的。满足以下条件则可以成为不可变类:
- 使用private和final修饰符来修饰该类的成员变量
- 提供带参的构造器用于初始化类的成员变量;
- 仅为该类的成员变量提供getter方法,不提供setter方法,因为普通方法无法修改fina修饰的成员变量;
- 如果有必要就重写Object类 的hashCode()和equals()方法,应该保证用equals()判断相同的两个对象其Hashcode值也是相等的。
JDK中提供的八个包装类和String类都是不可变类,我们来看看String的实现。
/** The value is used for character storage. */
private final char value[];
可以看出String的value就是final修饰的,上述其他几条性质也是吻合的。