一、final 介绍
在Java中,final
关键字有多种用途,可以用来修饰变量、方法和类。它的主要作用是确保所修饰的内容不可改变。
二、final 用法
1、修饰变量
1)局部变量
当一个局部变量被声明为final
时,它的值在初始化后就不能被改变。这意味着你只能对其赋值一次。
public class Example {
public static void main(String[] args) {
final int a = 0;
a++;// 这里会报错
}
}
2)成员变量
当一个成员变量被声明为final
时,它必须在定义时或者在构造器中或者在实例代码块中被初始化(如果在定义时或实例代码块中初始化了,则在构造器中就不能再次初始化了),初始化之后就不能再被改变。
class FinalVar {
private final int finalVar = 0;// 在定义时初始化
}
或
class FinalVar {
private final int finalVar;// 定义时不初始化
public FinalVar(int finalVar) {
this.finalVar = finalVar;// 在构造器中初始化
}
}
或
class FinalVar {
private final int finalVar;
{
finalVar = 0;// 在实例代码块中初始化
}
}
如果是按照下面这样写,就会报错:
class FinalVar {
private final int finalVar = 0;// 定义时初始化
public FinalVar(int finalVar) {
this.finalVar = finalVar;// 在构造器中再次赋值,这里会报错
}
}
因为 final 修饰的属性只能进行一次初始化,然后就不能改变了。
总结一下,也就是说对于被 final 修饰的实例属性,只能在以下三种位置的一种中被初始化:
- 定义时初始化
- 实例代码块中初始化
- 构造器中初始化
3)静态变量
final
关键字可以与static
一起使用来修饰类变量,通常用于创建常量。此时变量值在类被加载时初始化,并且其值不能被改变。
class FinalVar {
public static final double PI = 3.14;// 在声明时初始化,然后它将在类加载时被初始化
}
或
class FinalVar {
public static final double PI;
static {
PI = 3.14;// 在静态代码块中初始化,然后它将在类加载时被初始化
}
}
不能在构造器中初始化。
总结一下,对于被 final 修饰的静态属性,只能在以下两种位置的一种中初始化:
- 定义时
- 静态代码块中
2、修饰方法
当一个方法被声明为final
时,它不能被子类重写。如果你希望一个方法不能被子类重写时,可以使用 final 修饰这个方法。
虽然这个被 final 修饰的方法不能被子类重写,但是可以被子类继承下去。
class SuperClass {
public final void display() {
System.out.println("This is a final method.");
}
}
class SubClass extends SuperClass {
public void display() { // 错误: 不能重写final方法
System.out.println("Trying to override.");
}
}
3、修饰类
当一个类被声明为final
时,它不能被继承。当你不想让一个类被继承时,可以使用 final 修饰这个类。
虽然这个类不能被继承,但是可以被实例化。
final class FinalClass {
}
class SubClass extends FinalClass {
//这里会报错,没法继承一个final修饰的类
}
4、修饰方法参数
在方法参数中使用final
,意味着在方法内部不能改变该参数的引用。对于基本数据类型,值不能变;对于对象引用,引用不能变,但对象本身的状态可以改变。
public void method(final int parameter) {
parameter = 10; // 错误: 不能对final参数赋值
}
对于 final 修饰方法参数其实就相当于 final 修饰局部变量。
三、补充
- 如果一个类已经被 final 修饰了,那它的方法就没有必要再用 final 修饰了。
- final 不能修饰构造方法(构造器)。
- 一些常见的 final 类:对于包装类(Integer, Double, Boolean...)以及 String 类都是 final 类。
使用 final 修饰 static 成员变量,使用这个静态成员变量的时候,不会导致类加载,这是一个底层的优化。
public class Example {
public static void main(String[] args) {
System.out.println(FinalVar.PI);
}
}
class FinalVar {
public static final double PI = 3.14;
static {
// 这里用来测试是否进行了类加载
System.out.println("静态代码块执行~");
}
}
运行结果:
运行结果只有一个 3.14,没有静态代码块的执行,所以没有进行类加载。