大厂面试官问你知道final、finally、finalize有什么区别?

简介: Java程序员面试,基础真的很重要。基础这东西,各个公司都很看重,尤其是大公司,他们看中人的潜力,他们舍得花精力去培养,所以基础是重中之重。

前言
Java程序员面试,基础真的很重要。基础这东西,各个公司都很看重,尤其是大公司,他们看中人的潜力,他们舍得花精力去培养,所以基础是重中之重。之前很多人问我,项目经历少怎么办,那就去打牢基础,当你的基础好的发指的时候,你的其他东西都不重要了。

Java 语言有很多看起来很相似,但是用途却完全不同的语言要素,这些内容往往容易成为面试官考察你知识掌握程度的切入点。
今天,我要问你的是一个经典的 Java 基础题目,谈谈 final、finally、 finalize 有什么不同?
image

典型回答
final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。
finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9 开始被标记为 deprecated。

考点分析
这是一个非常经典的 Java 基础问题,我上面的回答主要是从语法和使用实践角度出发的,其实还有很多方面可以深入探讨,面试官还可以考察你对性能、并发、对象生命周期或垃圾收集基本过程等方面的理解。

对于final
推荐使用 final 关键字来明确表示我们代码的语义、逻辑意图,这已经被证明在很多场景下是非常好的实践,比如:
我们可以将方法或者类声明为 final,这样就可以明确告知别人,这些行为是不许修改的。
如果你关注过 Java 核心类库的定义或源码, 有没有发现 java.lang 包下面的很多类,相当一部分都被声明成为 final class?在第三方类库的一些基础类中同样如此,这可以有效避免 API 使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。
使用 final 修饰参数或者变量,也可以清楚地避免意外赋值导致的编程错误,甚至,有人明确推荐将所有方法参数、本地变量、成员变量声明成 final。
final 变量产生了某种程度的不可变(immutable)的效果,所以,可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值 final 变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。
final 也许会有性能的好处,很多文章或者书籍中都介绍了可在特定场景提高性能,比如,利用 final 可能有助于 JVM 将方法进行内联,可以改善编译器进行条件编译的能力等等。
坦白说,很多类似的结论都是基于假设得出的,比如现代高性能 JVM(如 HotSpot)判断内联未必依赖 final 的提示,要相信 JVM 还是非常智能的。类似的,final 字段对性能的影响,大部分情况下,并没有考虑的必要。
从开发实践的角度,我不想过度强调这一点,这是和 JVM 的实现很相关的,未经验证比较难以把握。我的建议是,在日常开发中,除非有特别考虑,不然最好不要指望这种小技巧带来的所谓性能好处,程序最好是体现它的语义目的。如果你确实对这方面有兴趣,可以查阅相关资料,我就不再赘述了,不过千万别忘了验证一下。

对于 finally
明确知道怎么使用就足够了。需要关闭的连接等资源,更推荐使用 Java 7 中添加的 try-with-resources 语句,因为通常 Java 平台能够更好地处理异常情况,编码量也要少很多,何乐而不为呢。

注意事项
finally代码不会被执行的特例:
image

final修饰的List,不会影响其行为:
image

final只能约束strList这个引用不可以被赋值,但是strList对象行为不被final影响,添加元素的操作是完全正常的。如果我们真的希望对象本身是不可变的,那么需要相应的类支持不可变的行为。
在上面的例子中,List.of方法创建的就是不可变List,最后那句add会在运行时抛出异常。
Java平台目前在逐步使用java.lang.ref.Cleaner来替换掉原来的finalize实现。

对于 finalize
我们要明确它是不推荐使用的,业界实践一再证明它不是个好的办法,在 Java 9 中,甚至明确将 Object.finalize() 标记为 deprecated!如果没有特别的原因,不要实现 finalize 方法,也不要指望利用它来进行资源回收。
为什么呢?简单说,你无法保证 finalize 什么时候执行,执行的是否符合预期。使用不当会影响性能,导致程序死锁、挂起等。
通常来说,利用上面的提到的 try-with-resources 或者 try-finally 机制,是非常好的回收资源的办法。如果确实需要额外处理,可以考虑 Java 提供的 Cleaner 机制或者其他替代方法。

相关文章
|
存储 算法 架构师
阿里面试:PS+PO、CMS、G1、ZGC区别在哪?什么是卡表、记忆集、联合表?问懵了,尼恩来一个 图解+秒懂+史上最全的答案
阿里面试:PS+PO、CMS、G1、ZGC区别在哪?什么是卡表、记忆集、联合表?问懵了,尼恩来一个 图解+秒懂+史上最全的答案
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
641 9
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
997 12
|
编译器 Android开发 开发者
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
Lambda表达式和匿名函数都是Kotlin中强大的特性,帮助开发者编写简洁而高效的代码。理解它们的区别和适用场景,有助于选择最合适的方式来解决问题。希望本文的详细讲解和示例能够帮助你在Kotlin开发中更好地运用这些特性。
426 9
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
343 14
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
386 3
|
前端开发 小程序 JavaScript
面试官:px、em、rem、vw、rpx 之间有什么区别?
面试官:px、em、rem、vw、rpx 之间有什么区别?
536 0