在Java中,final 关键字是一个非常有用的特性,它可以用来修饰类、方法和变量。final 的主要用途是使被修饰的对象成为“最终”的,即一旦被定义或初始化后就不能再改变。下面详细介绍 final 的不同用途及其使用场景:
1. final 修饰变量
不可变性:当 final 修饰一个变量时,该变量一旦被初始化就不能再被重新赋值。
常量:常量通常用 final 修饰,以表明它们的值不应该改变。通常这样的变量使用全大写字母命名,中间用下划线分隔单词,例如 public static final int MAX_VALUE = 100;。
使用场景:
定义常量,如数学常数 PI、E 等。标记不变的数据,如配置文件中的固定参数。防止变量被意外修改。
2. final 修饰方法(访问修饰符 final 返回类型 方法名(){})
不可覆盖:final 修饰的方法不能被子类覆盖(override)。
性能优化:在某些情况下,JVM 可能会对 final 方法进行内联优化,从而提高性能。
使用场景:
当想禁止子类覆盖某个方法时。当方法的实现不需要改变时。方法的性能至关重要时,使用 final 可以帮助 JVM 进行优化。
3. final 修饰类(final class 类名{})
不可继承:final 修饰的类不能被继承。
安全性和完整性:确保类的完整性和安全性。
使用场景:
当类的设计不允许被继承时。当类的实现是完整的,不希望其他类扩展它。
总结
final 修饰变量表示该变量的引用不可变,如果是基本类型则值不可变,如果是引用类型则引用指向的对象不可变(但对象的内容仍然可以改变)。
final 修饰方法表示该方法不能被子类覆盖。
final 修饰类表示该类不能被继承。
final修饰的属性,一般称之为常量。
final修饰的属性在定义时必须为其赋初值,并且以后不能再修改。
在定义时,直接为其赋初值。 public static final int MAX_VALUE = 100;也可以在构造器或者代码块中为其赋初值。
示例:
public class FinalTest02 {
public static void main(String[] args) {
FinalTest02001 obj1 = new FinalTest02001();
System.out.println(obj1.value); // 输出: 10
FinalTest02002 obj2 = new FinalTest02002();
System.out.println(obj2.value); // 输出: 20
FinalTest02003 obj3 = new FinalTest02003();
System.out.println(obj3.value); // 输出: 30
}
}
class FinalTest02001 {
public final int value = 10; // 在定义时初始化
public FinalTest02001() {
// 构造函数
}
}
class FinalTest02002 {
public final int value;
public FinalTest02002() {
value = 20; // 在构造器中初始化
}
}
class FinalTest02003 {
public final int value;
{
value = 30; // 在实例初始化代码块中初始化
}
public FinalTest02003() {
// 构造函数
}
}
但是当final修饰的属性是静态属性时,即static修饰,则初始化的位置只能是在定义时或者在静态代码块中,在构造器中是不能为其赋初值的。
示例:
public class FinalTest04 {
public static void main(String[] args) {
System.out.println(FinalTest04001.MAX_VALUE); // 输出: 100
System.out.println(FinalTest04002.MAX_VALUE); // 输出: 200
}
}
class FinalTest04001 {
public static final int MAX_VALUE = 100; // 在定义时初始化
}
class FinalTest04002 {
public static final int MAX_VALUE;
static {
MAX_VALUE = 200; // 在静态代码块中初始化
}
}
//导致编译错误
class FinalTest04003 {
public static final int MAX_VALUE;
public FinalTest04003() {
MAX_VALUE = 300; // 错误:无法从构造器中初始化静态变量
}
}
即使final修饰的类不能被继承,但是这个类仍然可以实例化对象。并且如果该类没有使用final修饰,但是含有final修饰的方法。 虽然该方法不能被重写,但是该方法可以被继承。
示例:
public class FinalTest05 {
public static void main(String[] args) {
FinalTest05001 a = new FinalTest05001();
FinalTest05002 b = new FinalTest05002();
a.myMethod(); // 调用 FinalTest05001 中的方法
b.myMethod(); // 调用 FinalTest05002 中的方法,因为不能被重写
}
}
class FinalTest05001 {
public final void myMethod() {
System.out.println("嘻嘻.");
}
}
class FinalTest05002 extends FinalTest05001 {
// 试图重写 final 方法会导致编译错误
// public void myMethod() {
// System.out.println("123");
// }
}