Java基础2 final关键字

Java基础2 final关键字

  在进行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(){}
}

//报错:final修饰的类不能被继承。
public final class SubClass extends SuperClass {

}
}

报错信息:

1
Error:(8, 41) java: 无法从最终com.exercise.Blog.FinalTest.SuperClass进行继承

2 修饰方法

final修饰的方法,不能被重写。实现final方法的目的:

  1. 方法锁定。防止任何继承类修改它的意义和实现。
  2. 高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//父类
//getName()方法使用final修饰
public class SuperClass {
public final void getName(){
System.out.println("Hello SuperClass");
}
}

//子类
//重写父类的被final修饰的getName()方法
public class SubClass extends SuperClass {
public void getName(){
System.out.println("Hello SubClass");
}
}

//调用子类的getName()方法
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修饰基本数据类型
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(int j) {
// this.j = j;
// }

//正确
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

参考

  1. https://zhuanlan.zhihu.com/p/33083924 深入浅出Java final关键字
  2. https://www.cnblogs.com/dolphin0520/p/3736238.html 浅析Java中的final关键字
  3. https://blog.csdn.net/u010002184/article/details/81347110 java,final变量初始化方式

  Java基础
You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.

评论