本文主要介绍了 final 关键字的基本使用方法及原理
final 关键字可以修饰类、方法和引用。修饰类,该类不能被继承。并且这个类的对象在堆中分配内存后地址不可变。
修饰方法,方法不能被子类重写。
修饰引用,引用无法改变,对于基本类型,无法修改值,对于引用,虽然不能修改地址值,但是可以对指向对象的内部进行修改。
比如 char[0] = ‘a’。不改变对象内存地址,只改变了值。
具体看一下下面的栗子:
final class Fi {
int a;
final int b = 0;
Integer s;
}
class Si{
// 一般情况下 final 修饰的变量一定要被初始化。
// 只有下面这种情况例外,要求该变量必须在构造方法中被初始化。
// 并且不能有空参数的构造方法。
// 这样就可以让每个实例都有一个不同的变量,并且这个变量在每个实例中只会被初始化一次
// 于是这个变量在单个实例里就是常量了。
final int s ;
Si(int s) {
this.s = s;
}
}
class Bi {
final int a = 1;
final void go() {
//final 修饰方法无法被继承
}
}
class Ci extends Bi {
final int a = 1;
// void go() {
// //final 修饰方法无法被继承
// }
}
final char[]a = {‘a’};
final int[]b = {1};
final 修饰类
@Test
public void final 修饰类 () {
// 引用没有被 final 修饰,所以是可变的。
//final 只修饰了 Fi 类型,即 Fi 实例化的对象在堆中内存地址是不可变的。
// 虽然内存地址不可变,但是可以对内部的数据做改变。
Fi f = new Fi();
f.a = 1;
System.out.println(f);
f.a = 2;
System.out.println(f);
// 改变实例中的值并不改变内存地址。
Fi ff = f;
// 让引用指向新的 Fi 对象,原来的 f 对象由新的引用 ff 持有。
// 引用的指向改变也不会改变原来对象的地址
f = new Fi();
System.out.println(f);
System.out.println(ff);
}
final 修饰方法
@Test
public void final 修饰方法 () {
Bi bi = new Bi();
bi.go();// 该方法无法被子类 Ci 重写
}
final 修饰基本数据类型变量和引用
<pre>
@Test
public void final 修饰基本类型变量和引用 () {
final int a = 1;
final int[] b = {1};
final int[] c = {1};
// b = c; 报错
b[0] = 1;
final String aa = “a”;
final Fi f = new Fi();
//aa = “b”; 报错
// f = null;// 报错
f.a = 1;
}