为了账号安全,请及时绑定邮箱和手机立即绑定

一文彻底搞懂:Java中final、finally、finalize的区别!

标签:
Java JavaScript

一文彻底搞懂:Java中final、finally、finalize的区别!

引子:面试官的经典三连问

那天阳光明媚,我信心满满地走进面试间。面试官微笑着说:“小伙子,Java基础不错啊,那我问个简单的——final、finally、finalize有什么区别?”

我心想:这不是送分题吗?正准备张口就来,却发现脑子里这三个词开始打架了。final是修饰符,finally是异常处理,finalize是…额…垃圾回收?但具体怎么用,区别在哪,一时间竟然说不清楚。

面试官看我支支吾吾,眼神中透出一丝"果然如此"的表情。那一刻我意识到,这看似简单的三兄弟,其实暗藏玄机。

探索:初识三兄弟

回家后,我决定彻底搞清楚这个问题。首先梳理一下基本概念:

关键字 类型 主要用途
final 修饰符 声明常量、防止继承/重写
finally 语句块 异常处理中的清理工作
finalize 方法 对象销毁前的最后处理

看起来很清晰,但魔鬼在细节里。

final:不变的承诺

final就像是Java世界里的"定海神针",一旦用它修饰,就意味着"此生不变"。

public final class ImmutableUser {
    private final String name;
    private final int age;
  
    public ImmutableUser(String name, int age) {
        this.name = name;  // 只能在构造器中赋值一次
        this.age = age;
    }
  
    // 无法被继承,无法修改字段值
}

finally:无论如何都要执行

finally就像是程序世界的"守门员",无论前面发生什么异常,它都要站好最后一班岗。

转折:踩坑瞬间

正当我以为掌握了这三兄弟的精髓时,实际项目中遇到了一个诡异的Bug。

我写了一个文件处理的方法,自信满满地用了finally来关闭资源:

public String processFile(String fileName) {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(fileName);
        // 处理文件逻辑
        return "success";
    } catch (Exception e) {
        return "error";
    } finally {
        if (fis != null) {
            fis.close();  // 这里可能抛出IOException!
        }
    }
}

结果线上偶尔报错:IOException in finally block

原来finally块里的代码也可能抛异常,而这个异常会"吞掉"try块中的原始异常。更要命的是,如果try和finally都有return语句,finally的return会覆盖try的return!

解决:核心思路揭秘

经过深入研究,我总结出了这三兄弟的精髓:

1. final的三重境界

  • 变量级别:一次赋值,终生不变
  • 方法级别:不可重写,但可以重载
  • 类级别:不可继承,如String、Integer

2. finally的正确打开方式

现代Java推荐用try-with-resources,它本质上就是finally的语法糖:

// 现代写法:自动资源管理
try (FileInputStream fis = new FileInputStream(fileName)) {
    // 处理文件
    return processData(fis);
} catch (IOException e) {
    log.error("文件处理失败", e);
    return "error";
}
// 编译器自动生成finally块来关闭资源

3. finalize的尴尬处境

finalize方法在Java 9后被标记为@Deprecated,因为:

  • 不可预测:何时调用完全由GC决定
  • 性能杀手:会延迟垃圾回收
  • 不可靠:可能永远不被调用

现在推荐用CleanerPhantomReference替代。

经验启示

通过这次深挖,我发现了几个有趣的规律:

记忆口诀

  • final:一锤定音,不可更改
  • finally:善始善终,必须执行
  • finalize:垂死挣扎,即将消失

实战建议

  • 优先使用final来提高代码安全性
  • 用try-with-resources替代手动finally
  • 避免使用finalize,选择现代替代方案

性能对比

方案 性能 可靠性 推荐度
final修饰 优秀 极高 ⭐⭐⭐⭐⭐
try-with-resources 良好 ⭐⭐⭐⭐⭐
手动finally 一般 中等 ⭐⭐⭐
finalize

总结:从菜鸟到老司机

回想起那次面试的窘迫,现在的我已经能够侃侃而谈这三兄弟的前世今生。技术的魅力就在于此——表面简单的概念,往往蕴含着深刻的设计哲学。

final教会我们约束的力量,finally体现了责任的担当,而finalize则是历史的教训。掌握它们,不仅仅是为了应付面试,更是为了写出更安全、更优雅的Java代码。

下次再有人问起这个经典问题,我会微笑着说:“这不仅仅是三个关键字,这是Java设计者留给我们的三堂人生课。”

本文转自渣哥https://zha-ge.cn/java/7

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消