1. final 关键字
final:最终的,被 final 关键字修饰,就不可以改变了。
final 可以修饰:
- 变量:表明该变量是常量,只能被赋值一次。
- 方法:表明该方法是最终方法,不能被重写。不想被别人改写的方法。
- 类:表明该类是最终类,不能被继承。
注:final 不可以修饰构造方法。
2. 使用 final 修饰变量
2.1 编译时常量
Java 编译期常量(compile-time constants)是指在编译时期就能被完全确定并被编译器替换其值的常量,减轻运行时负担。编译期常量:
- 声明为 final 的基本数据类型或 String 类型变量,并且在声明时进行初始化赋值。
- 初始值必须是一个在编译时就能确定的常量表达式,例如字面值常量或其他编译期常量的组合。
private final int valueOne = 1;
private static final int VALUE_TWO = 2;
valueOne 和 VALUE_TWO 均为编译期常量。使用 static 修饰的编译期常量全部使用大写字母命名,使用下划线连接。
当 final 修饰的变量是引用类型时,变量存储的地址值不能发生改变,对象内部可以改变。
public class Test {
public static void main(String[] args) {
final Student student = new Student("zhang", 18);
student.setName("Li");
student.setAge(20);
System.out.println(student.getName() + ":" +student.getAge());// Li:20
final int[] arr = {0, 1, 2, 3};
arr[0] = 11;
System.out.println(arr[0]);// 11
}
}
为什么字符串是不可变的?
// String.java
@Stable
private final byte[] value;
String 类中使用 final 修饰存储字符串的数组value,value指向的地址值不会改变。那存储的内容为什么不会改变呢?value 是 private 修饰的,并且 value 并没有提供 getter 和 setter 方法,所以字符串内容不会发生改变。
2.2 在运行时被初始化的常量
并不是使用 final 修饰的数据在编译时就可以知道它的值。
private static final int VALUE_THREE = new Random().nextInt(10);
VALUE_THREE 在运行时才会知道它的值。
3. 使用 final 修饰方法
3.1 将方法锁定
使用 final 修饰方法为了将方法锁定,以防止任何类修改方法含义,出于设计的考虑,想要确保在继承中方法行为保持不变。
3.2 效率(现已过时)
在 Java 的早期实现中,如果将一个方法指明为 final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。现在 Java 的实现中,虚拟机可以探测到这些情况,并优化去掉一些效率反而降低的额外的内嵌调用,因此不再需要使用 final 方法来进行优化了。
3.3.final 与 private
类中所有的 private 方法都隐式地指定为是 final 的。由于无法取用 private 方法,所以也就无法覆盖它。可以对 private 方法添加 final 修饰词,但这并不能给该方法增加任何额外的意义。
4. 使用 final 修饰类
使用 final 修饰类时,该类不能进行任何改变,也不能被继承。
由于 final 类禁止继承,所以 final 类中所有的方法都隐式指定为是 final 的。在 final 类中可以给方法添加 final 修饰词,不会增添任何意义。
网友评论