🧠 一句话理解 final
被
final
修饰的变量不可修改,方法不可重写,类不可继承。
🧱 用法 & 语法
✅ 1. final
修饰变量(常量)
final int x = 10;
x = 20; // ❌ 编译错误:不能修改 final 变量
🔹 特点:
-
修饰基本类型变量:值不能改
-
修饰引用类型变量:引用地址不能改,但对象内容可改
final StringBuilder sb = new StringBuilder("hello");
sb.append(" world"); // ✅ 允许修改内容
// sb = new StringBuilder(); // ❌ 不允许更改引用
✅ 场景:
-
定义常量(通常配合
static
使用)
public static final double PI = 3.14159;
通常全大写命名,表示全局不可修改常量
✅ 2. final
修饰方法
class A {
public final void show() {
System.out.println("Hello");
}
}
class B extends A {
// ❌ 编译错误:不能重写 final 方法
// public void show() { ... }
}
✅ 场景:
-
不希望子类重写某个方法(如工具类、安全逻辑)
-
保持方法逻辑的完整性(如
Object.equals()
自定义)
✅ 3. final
修饰类
final class Animal {
public void run() {
System.out.println("Animal runs");
}
}
// ❌ 编译错误:不能继承 final 类
// class Dog extends Animal {}
✅ 场景:
-
类逻辑不希望被扩展(如
String
类就是 final 的) -
保证类的安全性与不可更改行为
✅ 4. final
修饰形参(方法参数)
public void print(final int num) {
// num++; // ❌ 编译错误:不能修改参数值
System.out.println(num);
}
✅ 场景:
-
明确参数是只读的,提高代码可读性与安全性
-
在匿名内部类或 Lambda 中引用局部变量时必须是“有效 final”
✅ 5. final
修饰局部变量(for循环、try块等)
final int a = 100; // ✅ 必须初始化,否则编译报错
📌 final 的常见使用场景总结
场景 | 示例 | 意图 |
---|---|---|
定义常量 | public static final double PI | 不可修改的全局量 |
防止变量被意外修改 | final String name | 提高代码安全性与意图表达 |
禁止方法被重写 | final void log() | 保证父类逻辑不被子类改变 |
禁止类被继承 | final class UserService | 防止扩展,控制行为封装 |
匿名内部类中使用局部变量 | final int count = 10 | JDK 8 之后必须是“有效 final” |
⚠️ 易错点 & 注意事项
易错点 | 错误示例 | 正确理解 |
---|---|---|
1️⃣ 引用 final 不能改内容? | final List<String> list = ...; list.add("x"); | ✅ 可以改内容,不能换引用 |
2️⃣ final 方法是不是不能调用? | final void print() {} | ✅ 可以调用,只是不能被重写 |
3️⃣ final 一定要加 static 才是常量? | final double PI | ❌ 单独 final 是实例级常量,不是类常量 |
4️⃣ final 成员变量可以不初始化吗? | final int a; | ❌ 必须初始化(可在构造器中赋值) |
🧪 三种 final 使用
final class Constants {
public static final int MAX_USERS = 100;
}
class App {
public final void start() {
System.out.println("App started");
}
}
public class Main {
public static void main(String[] args) {
final StringBuilder sb = new StringBuilder("Hi");
sb.append(" there"); // ✅ 允许修改内容
System.out.println(sb.toString());
}
}