java 中的 final 关键字用于确保变量、方法和类的“最终性”,提供不可变性或不可继承性。1. 用于变量时,其值(基本类型)或引用(对象类型)一旦赋值便不可更改,但对象内部状态仍可变;2. 用于方法时,防止子类重写以固化行为,保障核心逻辑安全;3. 用于类时,禁止继承以实现不可变性或提升安全性;4. final 与 finally、finalize 不同:finally 用于异常处理后资源清理,finalize 是废弃的垃圾回收回调方法,三者功能和用途截然不同。

在 Java 的世界里,final 关键字就像一个承诺,一旦做出,便不可更改。它是一个非访问修饰符,主要用来声明变量、方法和类,其核心作用就是确保“最终性”——让被修饰的实体变得不可变、不可覆盖或不可继承。简单来说,它赋予了代码一种确定性,使得某些设计意图得以固化,从而提升程序的健壮性、可预测性和安全性。

final 关键字在 Java 中有着明确且重要的用途,它能够应用于变量、方法和类,每种应用场景都赋予了被修饰元素特定的“不变性”或“终结性”。
应用于变量时,final 变量一旦被赋值,其值就不能再被改变。对于基本数据类型,这意味着变量存储的数值本身是常量。而对于对象引用类型,final 确保的是这个引用本身不能再指向其他对象,但被引用的对象内部的状态(如果对象是可变的)仍然是可以改变的。这种特性常用于定义常量,或在多线程环境中确保某个引用不会被意外修改。
立即学习“Java免费学习笔记(深入)”;

应用于方法时,final 方法意味着该方法不能被任何子类重写(override)。这在设计框架或库时非常有用,可以确保某些核心逻辑或安全敏感操作的行为是固定的,不被子类随意篡改。它也常用于确保父类定义的特定行为在整个继承体系中保持一致性。
应用于类时,final 类表示该类不能被任何其他类继承。这通常用于创建不可变类(如 String 类),或者出于安全考虑,防止子类修改或扩展其行为。当一个类被声明为 final 后,它的设计就被认为是完整的,不需要也不允许再进行扩展。

final 变量:是值不可变还是引用不可变?这确实是初学者常会感到困惑的一个点,也是 final 变量最需要细致理解的地方。说白了,final 变量的“不可变”是针对其直接存储的内容而言的。
对于基本数据类型(如 int, double, boolean 等),final 关键字直接作用于变量所存储的那个值。一旦赋值,这个值就固定了,你不能再给它赋新值。
final int MAX_ATTEMPTS = 3; // MAX_ATTEMPTS = 4; // 编译错误:无法为最终变量 MAX_ATTEMPTS 分配值
而对于对象引用类型,final 关键字修饰的是引用本身。这意味着这个引用一旦指向了某个对象,它就不能再指向其他任何对象了。但是,被这个 final 引用所指向的对象内部的状态,如果这个对象本身是可变的(mutable),那么它的状态仍然是可以改变的。
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 这是允许的,改变的是 StringBuilder 对象内部的状态
System.out.println(sb.toString()); // 输出:Hello World
// sb = new StringBuilder("New"); // 编译错误:无法为最终变量 sb 分配值,因为引用不能改变所以,关键在于区分“引用不可变”和“被引用对象不可变”。如果你想要一个真正不可变的对象,你需要确保它的类本身就是不可变的(比如 String 类,它的内部状态一旦创建就不能改变),或者在设计自己的类时,让所有字段都是 final 并且它们引用的对象也都是不可变的。这其实是个挺有意思的设计哲学,在并发编程中尤其重要,因为不可变对象天生就是线程安全的。
final?声明方法或类为 final,通常是出于设计意图、安全性或性能(虽然性能提升在现代JVM中已不那么显著)的考虑。
对于 final 方法:
final 时,就明确告诉子类:“这个方法的行为是确定的,不要试图改变它。”这对于框架或库的开发者来说非常关键,可以确保其核心算法或业务逻辑不被使用者意外或恶意地修改,从而维护系统的完整性和稳定性。例如,在某些安全敏感的操作中,你绝对不希望它的行为被子类篡改。final 方法进行内联优化,因为编译器知道这个方法不会被重写,调用路径是确定的。但这在现代 JVM 中,智能优化器通常能够识别出哪些非 final 方法实际上也没有被重写,所以性能增益通常不是声明 final 的主要驱动力。对于 final 类:
final 类最常见的用途之一。如果一个类是 final 的,并且它的所有字段都是 final 的,同时确保这些字段引用的对象也是不可变的(或进行防御性拷贝),那么这个类的实例就是完全不可变的。String 类就是最典型的例子。不可变对象在多线程环境中非常安全,因为它们的状态不会改变,消除了竞态条件。java.lang.System 类就是 final 的,你无法继承它并修改其行为。final 时,意味着它的设计已经成熟和稳定,不打算再被继承扩展。这有助于维护 API 的稳定性和清晰性,避免未来因继承而产生的兼容性问题。final 方法,JVM 对 final 类也有一些优化空间,因为它知道不会有子类,可以简化某些方法调用的解析。final 与 finally、finalize 有什么区别?这三个词在 Java 中虽然拼写相似,但它们的作用、归属和设计意图完全不同,是初学者常常混淆的另一个“陷阱”。
final:
final int x = 10;, public final void myMethod() {}, public final class MyClass {}
finally:
try-catch 语句块中的一个伴随关键字,用于定义一个代码块。try 块中是否发生异常,finally 块中的代码都保证会执行。它通常用于释放资源,比如关闭文件流、数据库连接等,确保在任何情况下资源都能被正确清理。try {
// 可能会抛出异常的代码
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("捕获到异常:" + e.getMessage());
} finally {
System.out.println("finally 块执行,无论是否发生异常。");
// 资源清理代码
}finalize:
java.lang.Object 类中定义的一个方法(protected void finalize() throws Throwable)。finalize() 方法在现代 Java 中已被强烈不推荐使用,甚至在 Java 9 中被标记为废弃(deprecated for removal),并在后续版本中可能被移除。 它的执行时机不确定、无法保证,可能导致性能问题、死锁、资源泄露等一系列难以调试的复杂问题。try-with-resources 语句(针对实现了 AutoCloseable 接口的资源)或显式地在代码中管理资源的生命周期(如在构造函数中获取资源,在 finally 块中释放)。class MyResource {
// ... 资源相关代码
@Override
protected void finalize() throws Throwable {
try {
System.out.println("MyResource 对象正在被回收,执行 finalize。");
// 清理资源,如关闭文件句柄
} finally {
super.finalize(); // 总是调用父类的 finalize
}
}
}请务必记住,不要在生产代码中依赖 finalize 方法进行资源清理。
这三者虽然名字相似,但功能上是完全独立的,分别服务于 Java 语言中不同的设计目标:final 关乎“不变性”和“终结性”,finally 关乎“资源管理”和“异常处理流程”,而 finalize 则是一个被废弃的“垃圾回收回调”。理解它们的区别,是掌握 Java 语言深层机制的关键一步。
以上就是final 在java 中有什么作用?的详细内容,更多请关注php中文网其它相关文章!
java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号