【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 靠不住~

相关推荐
Joy T1 小时前
Spring AI 2.0 Agent 进阶:Memory、State 与 Context Engineering 常见技术全景
java·人工智能·后端·spring·agent入门·agent state
估值探索者1 小时前
【Python量化系统工程化 #08】关了 SSH 就停?systemd 让脚本开机自启 + 异常自动拉起
java·c++·人工智能·分类·数据挖掘
RAN11426760081 小时前
1.3第一个程序的介绍
开发语言·qt
天若有情6731 小时前
C++花式魔改!手写头文件复刻Java语法,彻底打破编码思维定式
java·c++·语言做语言·jac++
blue_ice .2 小时前
Verilog DDS 数字信号发生器:DAC 输出模拟波形与 ADC 回采观测
开发语言·单片机·嵌入式硬件·fpga开发
远翔调光芯片^138287988722 小时前
ECP5702能芯科技PD取电芯片在市场上的优势有哪些?
开发语言·人工智能·单片机·嵌入式硬件·智能家居
西峰u3 小时前
Java单例模式|从基础到多线程安全
java·java单例模式
ClinicTech3 小时前
实验室洗瓶机的清洗系统架构与自动化控制解析
java·python
linmengmeng_13143 小时前
【总结】MyBatis-Plus批量插入与清表的正确姿势
java·spring boot·mysql·mybatis
木井巳3 小时前
【记忆化搜索】不同路径
java·算法·leetcode·深度优先·剪枝·推荐算法