Java 中的 final 关键字
final 是 Java 中极具代表性的关键字核心含义是「不可修改、最终的」可作用于类、方法、变量三大场景是实现不可变性、提升代码安全性和性能的重要手段。本文从「基础用法→底层原理→实战场景→常见坑点」全维度拆解让你彻底掌握 final。一、final 关键字的核心定位final 字面意为「最终的、不可改变的」在 Java 中主要解决三类问题限制类被继承 → 避免子类修改核心逻辑限制方法被重写 → 固定方法行为限制变量被修改 → 实现常量 / 不可变对象。二、final 的三大核心用法1. 作用于类不可被继承语法与示例java运行// final 类不能被继承 public final class FinalClass { public void sayHello() { System.out.println(final类的方法); } } // 编译报错无法继承final类 // public class SubClass extends FinalClass {}核心特点final 类的所有方法自动成为 final 方法无需显式声明但成员变量可不是 final典型应用Java 核心类库中的String、Integer、Double等包装类、Math类都是 final 类避免核心类被篡改。设计意图保证类的核心逻辑不被子类破坏如 String 的不可变性提升 JVM 优化空间final 类无继承方法调用可静态绑定。2. 作用于方法不可被重写语法与示例java运行public class ParentClass { // final 方法子类不能重写 public final void finalMethod() { System.out.println(父类final方法); } public void normalMethod() { System.out.println(父类普通方法); } } public class ChildClass extends ParentClass { // 编译报错无法重写final方法 // Override // public void finalMethod() {} // 合法重写普通方法 Override public void normalMethod() { System.out.println(子类重写普通方法); } }核心特点final 方法仅限制「重写」不限制「重载」java运行public class MethodDemo { public final void test(int a) {} // 合法重载参数列表不同 public final void test(String a) {} }private 方法隐式为 final 方法子类无法访问自然无法重写。设计意图固定核心方法的行为如工具类的核心算法方法调用时可触发「内联优化」JVM 认为方法不会被重写直接嵌入代码。3. 作用于变量不可被重新赋值final 变量是最常用的场景细分三类变量局部变量、成员变量、静态变量核心规则必须初始化且初始化后不可修改引用 / 值。1局部变量java运行public void localVarDemo() { // 方式1声明时初始化 final int a 10; // 编译报错无法为最终变量a分配值 // a 20; // 方式2先声明后初始化仅一次 final int b; b 20; // 编译报错 // b 30; // final 引用类型引用不可变对象内容可变 final User user new User(张三, 20); // 编译报错引用不能重新指向新对象 // user new User(李四, 25); // 合法对象属性可修改 user.setAge(21); }2成员变量实例变量必须在「声明时、构造器、初始化块」中任选其一初始化否则编译报错java运行public class MemberVarDemo { // 方式1声明时初始化 final String name 张三; // 方式2初始化块初始化 final int age; { age 20; } // 方式3构造器初始化支持动态赋值 final String email; public MemberVarDemo(String email) { this.email email; } // 编译报错未初始化final变量 // final double score; }3静态变量类变量必须在「声明时、静态初始化块」中初始化不能在构造器中初始化java运行public class StaticVarDemo { // 方式1声明时初始化最常用定义常量 public static final double PI 3.1415926; // 方式2静态初始化块初始化 public static final String VERSION; static { VERSION 1.0.0; } // 编译报错静态final变量不能在构造器初始化 // public static final int MAX_SIZE; // public StaticVarDemo() { // MAX_SIZE 100; // } }核心规则变量表格变量类型初始化时机能否修改局部变量声明时 或 使用前仅一次不可重新赋值成员变量声明时 / 初始化块 / 构造器仅一次不可重新赋值静态变量声明时 / 静态初始化块仅一次不可重新赋值引用类型变量引用不可变对象内容可变引用不可改属性可改基本类型变量值不可变完全不可改三、final 的底层原理与优化1. 编译期常量 vs 运行时常量编译期常量static final且声明时初始化如PI3.14编译时直接替换为字面量提升性能java运行// 编译后System.out.println(3.1415926); System.out.println(StaticVarDemo.PI);运行时常量static final但在静态块初始化如VERSION运行时才赋值无法编译期替换。2. 不可变对象的实现final 是实现不可变对象的核心如 String规则类声明为 final避免继承所有成员变量声明为 final private无 setter 方法仅提供 getter构造器中初始化所有成员变量。示例自定义不可变类java运行public final class ImmutableUser { private final String id; private final String name; private final int age; public ImmutableUser(String id, String name, int age) { this.id id; this.name name; this.age age; } // 仅提供getter无setter public String getId() { return id; } public String getName() { return name; } public int getAge() { return age; } }3. JVM 优化方法内联final 方法不会被重写JVM 可安全地将方法代码内联到调用处减少方法调用开销常量折叠编译期常量直接替换为字面量避免运行时查找指令重排限制final 变量初始化完成前不会被其他线程可见保证内存可见性。四、final 的常见坑点与避坑指南1. 坑点 1final 引用类型变量的误区java运行// 错误认知final User 是不可变对象 final User user new User(张三, 20); user.setAge(21); // 合法仅引用不可变对象内容可变 // 正确做法若需对象完全不可变需按不可变类规则设计2. 坑点 2final 方法的重载 vs 重写java运行public class MethodPitfall { public final void test(int a) {} // 合法重载参数不同 public final void test(String a) {} public class Sub extends MethodPitfall { // 合法不是重写参数不同是子类新方法 public void test(String a) {} } }3. 坑点 3final 变量的初始化时机java运行public class InitPitfall { final int a; // 编译报错构造器中未初始化所有final变量 // public InitPitfall() {} // 合法构造器初始化 public InitPitfall(int a) { this.a a; } }4. 坑点 4final 与匿名内部类匿名内部类访问的局部变量必须是 final 或「有效 final」JDK8java运行public class InnerClassDemo { public void test() { int num 10; // JDK8 自动视为有效final // num 20; // 若修改编译报错 Runnable runnable new Runnable() { Override public void run() { System.out.println(num); // 必须是final/有效final } }; } }五、final 的实战场景1. 定义常量最常用java运行// 标准常量定义public static final 大写命名 public class Constant { // 系统编码 public static final String CHARSET UTF-8; // 超时时间 public static final int TIMEOUT 5000; // 数学常量 public static final double E 2.71828; }2. 保证方法行为稳定java运行// 工具类核心方法避免子类重写破坏逻辑 public class StringUtil { public final boolean isEmpty(String str) { return str null || str.length() 0; } }3. 实现不可变对象如自定义不可变配置类、不可变数据传输对象DTOjava运行public final class ConfigDTO { private final String appId; private final String appSecret; private final int timeout; public ConfigDTO(String appId, String appSecret, int timeout) { this.appId appId; this.appSecret appSecret; this.timeout timeout; } // 仅getter无setter public String getAppId() { return appId; } public String getAppSecret() { return appSecret; } public int getTimeout() { return timeout; } }4. 方法参数不可变java运行// 保证方法内不修改入参引用 public void process(final User user) { // 编译报错不能修改final参数引用 // user new User(); // 合法修改对象属性若需完全不可变需传入不可变对象 user.setAge(20); }六、常见面试题final 关键字的作用作用于类不可继承作用于方法不可重写作用于变量不可重新赋值。final、finally、finalize 的区别final关键字限制不可变finally异常处理关键字保证代码块必执行finalizeObject 方法垃圾回收前调用已废弃。final 引用类型变量的特点引用不可变对象内容可变若需对象完全不可变需设计为不可变类。static final 常量的初始化时机声明时或静态初始化块编译期常量声明时初始化会被常量折叠优化。为什么 String 是 final 类保证字符串不可变实现字符串常量池、线程安全、哈希值缓存等核心特性。总结核心语义final 表示「不可变」作用于类不可继承、方法不可重写、变量不可重新赋值变量规则final 变量必须初始化局部变量声明 / 使用前成员变量声明 / 初始化块 / 构造器静态变量声明 / 静态块关键细节引用类型 final 变量仅引用不可变对象内容可变final 方法可重载不可重写static final 编译期常量可触发 JVM 优化核心价值提升代码安全性不可篡改、性能JVM 优化、可读性明确不可变语义。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2442516.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!