--- title: "01-final关键字" created: 2025-11-26 tags: - Java --- # final关键字 ## 核心概念 `final`是Java中的一个重要关键字,可以修饰类、方法和变量,提供了不可变性和性能优化的能力。理解`final`的使用场景和底层机制,是编写高质量Java代码的关键。 --- ## 一、final修饰变量 ### 1.1 基本用法 ```java public class FinalDemo { // 1. 编译期常量 public static final int CONSTANT = 100; // 2. 运行时常量(必须在构造函数中初始化) private final int runtimeConstant; public FinalDemo(int value) { this.runtimeConstant = value; } // 3. final局部变量 public void method() { final int localFinal = 200; // localFinal = 300; // ❌ 编译错误 } } ``` ### 1.2 引用类型的final ```java public class FinalReferenceDemo { // final引用:引用不可变,但对象可以修改 private final List list = new ArrayList<>(); public void modifyList() { // ✅ 可以修改列表内容 list.add("Hello"); list.remove(0); // ❌ 不能重新赋值引用 // list = new ArrayList<>(); // 编译错误 } // final参数 public void processData(final User user) { // user = new User(); // ❌ 编译错误 user.setName("New Name"); // ✅ 可以修改对象内部状态 } } ``` ### 1.3 final的内存语义 ```java public class FinalMemoryDemo { // final变量的内存可见性 private final int x; private final int y; public FinalMemoryDemo() { x = 1; // 写入final变量 y = 2; // happens-before原则 } public void method() { // x和y的值对所有线程可见 System.out.println(x + y); } } ``` --- ## 二、final修饰方法 ### 2.1 防止方法重写 ```java public class Parent { // 不允许子类重写 public final void method() { System.out.println("Cannot be overridden"); } } class Child extends Parent { // ❌ 编译错误 // @Override // public void method() { } } ``` ### 2.2 性能优化 ```java public class OptimizationDemo { // JVM可以内联final方法,提高性能 public final int calculate(int a, int b) { return a + b; } } ``` --- ## 三、final修饰类 ### 3.1 阻止继承 ```java // 不允许被继承 public final class ImmutableClass { private final int value; public ImmutableClass(int value) { this.value = value; } } // ❌ 编译错误 // class SubClass extends ImmutableClass { } ``` ### 3.2 不可变类的设计 ```java public final class Money { private final int amount; private final String currency; public Money(int amount, String currency) { this.amount = amount; this.currency = currency; } // 只读方法 public int getAmount() { return amount; } public String getCurrency() { return currency; } // 创建新对象,而不是修改 public Money add(Money other) { if (!this.currency.equals(other.currency)) { throw new IllegalArgumentException("Cannot add different currencies"); } return new Money(this.amount + other.amount, this.currency); } } ``` --- ## 四、final的性能优化 ### 4.1 编译器优化 ```java public class OptimizationDemo { // 编译器可以进行常量折叠 public static final int MAGIC_NUMBER = 42; public int calculate() { // 编译后可能直接替换为 return 84; return MAGIC_NUMBER * 2; } } ``` ### 4.2 JVM内联 ```java public class InlineDemo { // final方法更容易被JVM内联 public final int add(int a, int b) { return a + b; } public void process() { int result = add(10, 20); // 可能被直接替换 } } ``` --- ## 五、高频面试题 ### Q1: final和finally有什么区别? **答:** - `final`:修饰不可变的变量、方法或类 - `finally`:异常处理中的finally块,无论是否异常都会执行 ### Q2: final变量必须在声明时初始化吗? **答:** - 静态final变量:必须在声明时或静态块中初始化 - 实例final变量:可以在声明、构造函数或初始化块中初始化 ### Q3: final修饰引用类型变量时什么意思? **答:** - 引用不可变:不能重新赋值 - 对象内部状态可以修改 - 类似于引用的"只读" ### Q4: final方法的性能优势是什么? **答:** - JVM可以内联final方法 - 编译器可以进行更多优化 - 方法调用开销降低 ### Q5: 为什么String类是final的? **答:** - 线程安全 - 字符串常量池需要不可变性 - 防止被恶意继承和修改 --- ## 六、最佳实践 ### ✅ 推荐做法 ```java // 1. 常量使用final public static final double PI = 3.14159; // 2. 不可变类设计 public final class ImmutableUser { private final String name; private final int age; } // 3. 方法性能优化 public final int calculate(int a, int b) { return a + b; } ``` ### ❌ 避免做法 ```java // 1. 避免过度使用final public final class TooRestrictive { // 过度限制,降低灵活性 } // 2. final不等于完全不可变 public final class WeakImmutability { private final List list; // list内容仍可以修改 } ``` --- ## 相关链接 - [[02-static关键字|02-static关键字]] - [[01-继承与多态|01-继承与多态]] - [[01-封装|不可变对象设计]](含不可变对象专节) --- ## 记忆口诀 ``` final修饰不可变,变量方法类为先 引用不能重新指,对象内部可更新 性能优化靠内联,编译器帮你加速间 不可继承不可改,安全高效是真谛 ``` --- ⬅️ [[07-面向对象设计的SOLID原则|面向对象设计的SOLID原则]] 🏠 [[00-Java|00-Java]] ➡️ [[02-static关键字|static关键字]]