final关键字

final 被译为 “最后的”、“最终的”,final 是 Java 语言中的一个关键字,凡是被 final 关键字修饰过的内容都是不可改变的。本节将讲解 final 关键字的 3 种使用场景。

final关键字

final 关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final 关键字定义的变量为常量。例如,在类中定义 PI 值,可以使用如下语句:

final double PI = 3.14;

当在程序中使用了 PI 这个常量时,它的值就是 3.14。如果在程序中再次对定义为 final 的常量进行赋值,那么编译器将不会接受。

由 final 关键字定义的变量必须在声明时对其进行赋值操作。final 关键字除了可以修饰基本数据类型的常量,还可以修饰对象引用。由于数组也可以被看作一个对象来引用,因此 final 关键字可以修饰数组。一个对象引用一旦被修饰为 final 关键字后,它就只能恒定指向一个对象,无法将其改变以指向另一个对象。一个既是 static 又是 final 的字段只占据一段不能改变的存储空间。为了深入了解 final 关键字,来看下面的实例。

【例7.10】定义不允许被修改的常量π(实例位置:资源包\TM\sl\7\10)

创建 FinalData 类,在该类中定义表示圆周率的常量 PI,并尝试修改 PI 的值。

public class FinalData {
    static final double PI = 3.1415926;
    public static void main(String[] args) {
        System.out.println("圆周率的值为:" + PI);
        System.out.println("半径为3的圆的周长为:" + (2*3*PI));
        PI = 3.1415927;   // 尝试修改PI的值
    }
}

本实例在运行之前,Eclipse 就会报出如图7.7所示的编译错误。常量 PI 不允许被修改。

image 2024 02 29 18 09 42 827
Figure 1. 图7.7 修改final的常量时发生的编译错误

final方法

将方法定义为 final 类型,可以防止子类修改父类的定义与实现方式,同时定义为 final 的方法的执行效率要高于非 final 方法。在修饰权限中曾经提到过 private 修饰符,如果一个父类的某个方法被设置为 private,子类将无法访问该方法,自然无法覆盖该方法。也就是说,一个定义为 private 的方法被隐式地指定为 final 类型,因此无须将一个定义为 private 的方法再定义为 final 类型。例如下面的语句:

private final void test() {
    ...   // 省略一些程序代码
}

【例7.11】使用final关键字为电视机上儿童锁(实例位置:资源包\TM\sl\7\11)

创建 Dad 爸爸类,给 Dad 类定义一个打开电视机的方法,该方法使用 final 关键字修饰。创建 Dad 类的子类 Baby 类,让 Baby 类尝试自己重写打开电视的方法。

class Dad {
	public final void turnOnTheTV() {
		System.out.println("爸爸打开了电视");
	}
}

class Baby extends Dad {
	public final void turnOnTheTV() {
		System.out.println("宝宝也要打开电视");
	}
}

本实例在运行之前,Eclipse 就会报出如图7.8所示的编译错误。因为打开电视这个方法是由 final 关键字修饰的,子类无法被重写。所以 Baby 想要打开电视,就只能找爸爸来打开了。

image 2024 02 29 18 14 31 196
Figure 2. 图7.8 final方法无法被重写

final类

定义为 final 的类不能被继承。如果希望一个类不被任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类设置为 final 类。final 类的语法如下:

final 类名{}

如果将某个类设置为 final 类,则该类中的所有方法都被隐式地设置为 final 方法,但是 final 类中的成员变量可以被定义为 final 或非 final 形式。

例如,已知 JDK 的 java.lang 包下的 Math 数学类和 String 字符串类都是由 final 关键字修饰的类,这两个类就无法做任何类的父类,如果这两个类出现在 extends 右侧,就会发生编译错误,如图7.9所示。

image 2024 02 29 18 16 10 809
Figure 3. 图7.9 final类无法被继承

编程训练(答案位置:资源包\TM\sl\7\编程训练)

【训练11】创建月球类 因为地球周围没有其他类似月球的卫星,所以月球类不能有子类。

【训练12】交通信号灯 编写交通类,把表示遵守交通规则的方法设为final方法,不管是行人、非机动车,还是机动车,要遵守的交通规则都是一样的。在行至有交通信号灯的路口时,要遵守“红灯停、绿灯行”的交通规则。