在进行Java编程的时候,我们通常会使用final修饰那些不想改变的数据,这样往往出于效率、设计的目的。final
可以修饰类、方法、属性。
1 修饰类
final
修饰的类,不能被继承。
1 2 3 4 5 6 7 8 9 10 11
| public class FinalTest { public final class SuperClass { public SuperClass(){} }
public final class SubClass extends SuperClass {
} }
|
报错信息:
1
| Error:(8, 41) java: 无法从最终com.exercise.Blog.FinalTest.SuperClass进行继承
|
2 修饰方法
final
修饰的方法,不能被重写。实现final
方法的目的:
- 方法锁定。防止任何继承类修改它的意义和实现。
- 高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
public class SuperClass { public final void getName(){ System.out.println("Hello SuperClass"); } }
public class SubClass extends SuperClass { public void getName(){ System.out.println("Hello SubClass"); } }
public class FinalTest { public static void main(String[] args) { SuperClass sup = new SubClass(); sup.getName(); } }
|
报错信息:
1
| Error:(4, 12) java: com.exercise.Blog.SubClass中的getName()无法覆盖com.exercise.Blog.SuperClass中的getName()被覆盖的方法为final
|
3 修饰变量
基本数据类型
final
修饰基本数据类型,当给基本类型初始化之后,不能再重新赋值,否则报错。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class FinalTest { public static void main(String[] args) { final int num = 5; System.out.println("num的值为"+num); num = 10; System.out.println("num的值为"+num); } }
|
报错信息:
1
| Error:(10, 9) java: 无法为最终变量num分配值
|
引用数据类型
final
修饰引用类型,当final
变量初始化之后,final
不能重新指向新的变量,但是指向变量的内容可以改变。
1 2 3 4 5 6 7 8 9 10
| public class FinalTest { public static void main(String[] args) {
final StringBuilder str = new StringBuilder("yu"); System.out.println("修改前str的值为"+str);
str.append("yu"); System.out.println("修改后str的值为"+str); } }
|
执行结果:
1 2
| 修改前str的值为yu 修改后str的值为yuyu
|
在上面的demo中,str
刚开始指向yu
这个字符串,之后调用append()
函数,字符串变为yuyu
。但是str
的指向没有变化。所以,对于final
修饰的引用类型,指向变量的内容可以改变。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class FinalTest { public static void main(String[] args) {
final StringBuilder str = new StringBuilder("yu"); System.out.println("修改前str的值为"+str);
str.append("yu"); System.out.println("修改后str的值为"+str);
str = new StringBuilder("yuNew"); System.out.println("指向别的str的值为"+str); } }
|
报错信息:
1
| Error:(10, 9) java: 无法为最终变量str分配值
|
在上面的demo中,str
刚开始指向yu
这个字符串,之后调用append()
函数,字符串变为yuyu
,接着使用str
的指向新的字符串yuNew
,产生错误信息。所以,对于final
修饰的引用类型,不能重新指向新的变量。
注意
当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class FinalTest2 {
private final static int i = 0;
private final int j;
private final static int k;
private final int m;
public FinalTest2() { this.j = 1; }
static { k = 2; }
{ m = 3; }
public static void main(String[] args) { FinalTest2 n = new FinalTest2(); System.out.println("声明时直接初始化的i值为"+i); System.out.println("构造函数赋值的j值为"+n.j); System.out.println("静态代码块赋值的k值为"+k); System.out.println("构造代码块赋值的m值为"+n.m); } }
|
1 2 3 4
| 声明时直接初始化的i值为0 构造函数赋值的j值为1 静态代码块赋值的k值为2 构造代码块赋值的m值为3
|
参考
- https://zhuanlan.zhihu.com/p/33083924 深入浅出Java final关键字
- https://www.cnblogs.com/dolphin0520/p/3736238.html 浅析Java中的final关键字
- https://blog.csdn.net/u010002184/article/details/81347110 java,final变量初始化方式