【Java】final、finally、finalize 区别

这三个关键字长得像,但作用和所属范畴完全不同,是Java面试的经典高频题。

一、核心区别表

关键字 核心作用 所属范畴 使用场景 关键特点
final 限制修改(不可变) 修饰符 修饰变量/方法/类 编译期生效,手动编码控制不可变性
finally 保证代码块必执行 异常处理 try-catch-finally 结构中 运行期生效,无论是否抛异常都执行
finalize 对象回收前的回调方法 垃圾回收(GC) Object类的方法,可重写 运行期由GC调用,执行时机不可控

二、通俗解读

1. final:"最终的"------给代码加"不可修改锁"

通俗理解

final 是"修饰符",核心是禁止修改

  • 修饰变量:值/引用地址不可变;
  • 修饰方法:子类不能重写;
  • 修饰类:不能被继承。
代码示例
java 复制代码
// 1. final修饰变量(基本类型值不可变,引用类型地址不可变)
final int MAX_NUM = 100;
// MAX_NUM = 200; // 编译报错:值不可改

final User user = new User("张三");
// user = new User("李四"); // 编译报错:地址不可改
user.setAge(25); // 合法:对象内部内容可改

// 2. final修饰方法(子类不能重写)
class Parent {
    public final void coreMethod() {}
}
// class Child extends Parent {
//     @Override
//     public void coreMethod() {} // 编译报错:不能重写
// }

// 3. final修饰类(不能被继承)
final class FinalClass {}
// class SubClass extends FinalClass {} // 编译报错:不能继承

2. finally:"最终的"------异常处理的"兜底代码块"

通俗理解

finally 是"异常处理结构的一部分",核心是保证执行

  • 无论 try 块是否抛异常、catch 块是否捕获,finally 块一定执行;
  • 唯一例外:执行 System.exit(0) 强制终止JVM时,finally 不执行。
代码示例
java 复制代码
public static void testFinally() {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream("test.txt");
        // 模拟异常
        int a = 1 / 0;
    } catch (Exception e) {
        System.out.println("捕获异常:" + e.getMessage());
    } finally {
        // 必执行:释放资源(如关闭流、数据库连接)
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("finally块执行:资源已释放");
    }
}

// 调用结果:
// 捕获异常:/ by zero
// finally块执行:资源已释放

3. finalize:"最终化"------GC回收对象前的"遗言方法"

通俗理解

finalize 是 Object 类的保护方法,核心是:

  • GC回收对象前会调用该方法,给对象最后一次释放资源的机会;
  • 执行时机不可控(GC何时运行不确定),已被JDK9标记为过时(推荐用 try-with-resources 替代)。
代码示例
java 复制代码
class Resource {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        // GC回收前执行:释放资源(不推荐依赖)
        System.out.println("对象即将被GC回收,执行finalize");
    }
}

public static void testFinalize() {
    // 创建对象,之后变为垃圾(无引用)
    new Resource();
    // 手动触发GC(仅建议,不保证立即执行)
    System.gc();
}

// 可能的输出(执行时机不确定):
// 对象即将被GC回收,执行finalize

三、高频追问

追问1:finally 块一定会执行吗?

答:不一定!只有以下情况 finally 不会执行:

  1. 执行 System.exit(0) 强制终止JVM;
  2. 线程被杀死(如 Thread.stop());
  3. JVM崩溃(如硬件故障、强制关闭进程)。
    其余情况(包括 try 块 return、catch 块抛异常),finally 都会执行。

追问2:try-catch-finally 中 return 的执行顺序?

答:finally 块在 return 之前执行(面试常考陷阱题):

java 复制代码
public static int testReturn() {
    try {
        return 1;
    } finally {
        System.out.println("finally执行");
        // 注意:finally中return会覆盖try的return值(不推荐这么写)
        // return 2;
    }
}

// 调用结果:
// finally执行
// 返回值:1

追问3:为什么不推荐使用 finalize?

答:

  1. 执行时机不可控:GC运行时间不确定,finalize 可能很久才执行,甚至不执行;
  2. 性能差:会延长对象回收周期,增加GC负担;
  3. 已过时:JDK9后标记为 @Deprecated,推荐用 try-with-resources、手动关闭资源等方式替代。

四、总结

请说说 final、finally、finalize 的区别?

答:

  1. final:是修饰符,核心作用是限制修改------修饰变量时值/地址不可变,修饰方法时不可被重写,修饰类时不可被继承,编译期生效;
  2. finally:是异常处理的一部分,用于 try-catch-finally 结构中,核心作用是保证代码块必执行(除非JVM强制终止),常用于释放资源(如关闭流、数据库连接),运行期生效;
  3. finalize :是 Object 类的保护方法,GC回收对象前会调用该方法,给对象最后一次释放资源的机会,但执行时机不可控,已被JDK9标记为过时,不推荐使用。
    补充:三者仅拼写相似,核心作用和使用场景完全不同,final 关注"不可变",finally 关注"必执行",finalize 关注"GC回收前的回调"。

总结(关键点回顾)

  1. final:修饰符,管"不可变"(变量/方法/类);
  2. finally:异常处理,管"必执行"(释放资源);
  3. finalize:GC相关,管"回收前回调"(已过时,不推荐用);
  4. 核心区分:final 是编译期的"限制",finally 是运行期的"保证",finalize 是运行期的"不可控回调"。

简单记:final 改不了,finally 跑不掉,finalize 靠不住~

相关推荐
yeflx2 小时前
C++纯虚接口
开发语言·c++
代码探秘者2 小时前
【Java】浅拷贝 VS 深拷贝:核心差异 + 实现方式 + 避坑指南
java·开发语言
盐水冰2 小时前
【Redis】学习(3)Redis的Java客户端
java·redis·学习
阿星仔6662 小时前
claude code switch安装使用指南:一键切换多Claude API
java
weixin199701080162 小时前
淘宝客商品详情页前端性能优化实战
java·前端·python·性能优化
程途知微2 小时前
Java 内存模型 (JMM) 与 volatile 底层实现
java·后端
Joker Zxc2 小时前
【前端基础(Javascript部分)】5、JavaScript的循环语句
开发语言·前端·javascript
何中应2 小时前
IDEA中三个很方便的设置
java·ide·intellij-idea