[Java基础面试题一]深入谈谈final、finally、 finalize 有什么不同?吊打面试官

简介: [Java基础面试题一]深入谈谈final、finally、 finalize 有什么不同?吊打面试官

[Java基础面试题一]深入谈谈final、finally、 finalize 有什么不同?吊打面试官


文章目录

一、前言

二、典型回答

三、深入谈final

四、深入谈finally

五、深入谈finalize

六、总结


一、前言

作为Java后端开发者,小编在面试过程中90%都会问到的Java基础面试题: final、finally、 finalize 有什么不同?

以前都是简单说说用法和实践角度回答的.直到看了极客时间的课程在知道自己回答只是皮毛,路很长,写一篇博客出来让大家一起学习,如有侵权,联系删除哈!!!


课程地址


二、典型回答

- final

可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,大部分定义为常量,而 final 的方法也是不可以重写的(override)。


- finally

则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁、还有可以当做if else作为判断语句等动作。


- finalize

是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9 开始被标记为 deprecated。


三、深入谈final

推荐使用 final 关键字来明确表示我们代码的语义、逻辑意图,这已经被证明在很多场景下是非常好的实践,比如:


我们可以将方法或者类声明为 final,这样就可以明确告知别人,这些行为是不许修改的。

如果你关注过 Java 核心类库的定义或源码, 有没有发现 java.lang 包下面的很多类,相当一部分都被声明成为 final class?在第三方类库的一些基础类中同样如此,这可以有效避免 API 使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。


使用 final 修饰参数或者变量,也可以清楚地避免意外赋值导致的编程错误,甚至,有人明确推荐将所有方法参数、本地变量、成员变量声明成 final。

final 变量产生了某种程度的不可变(immutable)的效果,所以,可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值 final 变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。

final 也许会有性能的好处,很多文章或者书籍中都介绍了可在特定场景提高性能,比如,利用 final 可能有助于 JVM 将方法进行内联,可以改善编译器进行条件编译的能力等等。坦白说,很多类似的结论都是基于假设得出的,比如现代高性能 JVM(如 HotSpot)判断内联未必依赖 final 的提示,要相信 JVM 还是非常智能的。类似的,final 字段对性能的影响,大部分情况下,并没有考虑的必要。


从开发实践的角度,我不想过度强调这一点,这是和 JVM 的实现很相关的,未经验证比较难以把握。我的建议是,在日常开发中,除非有特别考虑,不然最好不要指望这种小技巧带来的所谓性能好处,程序最好是体现它的语义目的。


四、深入谈finally

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


- try-catch-finally

try (InputStream is = new FileInputStream("test.txt")) {
  is.read();
  ...
} catch(Exception e) {
  e.printStackTrace();
} finally {
  is.close();
  //无需添加关闭InputStream输入流的代码,其close()方法会自行调用
}

- TWR(推荐)

//无需添加关闭InputStream输入流的代码,其close()方法会自行调用
try (InputStream is = new FileInputStream("test.txt")) {
  is.read();
  ...
} catch(Exception e) {
  e.printStackTrace();
}

- fianlly 不会被执行的情况

try-cach 异常退出

try{
  system.exit(1)
}catch(Exception e) {
  e.printStackTrace();
}finally{
  System.out.println("看得到我吗?");
}

try-cach 程序正常退出

try{
  system.exit(0)
}catch(Exception e) {
  e.printStackTrace();
}finally{
  System.out.println("看得到我吗?");
}

死循环

try{
  while(ture){
    System.out.println("循环死你!!");
  }
}catch(Exception e) {
  e.printStackTrace();
}finally{
  System.out.println("看得到我吗?");
}


五、深入谈finalize

finalize 的执行是和垃圾收集关联在一起的,一旦实现了非空的 finalize 方法,就会导致相应对象回收呈现数量级上的变慢,有人专门做过 benchmark,大概是 40~50 倍的下降。

因为,finalize 被设计成在对象被垃圾收集前调用,这就意味着实现了 finalize 方法的对象是个“特殊公民”,JVM 要对它进行额外处理。finalize 本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能被回收。

有人也许会问,我用 System.runFinalization() 告诉 JVM 积极一点,是不是就可以了?也许有点用,但是问题在于,这还是不可预测、不能保证的,所以本质上还是不能指望。实践中,因为 finalize 拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致 OOM 的原因。

从另一个角度,我们要确保回收资源就是因为资源都是有限的,垃圾收集时间的不可预测,可能会极大加剧资源占用。这意味着对于消耗非常高频的资源,千万不要指望 finalize 去承担资源释放的主要职责,最多让 finalize 作为最后的“守门员”,况且它已经暴露了如此多的问题。这也是为什么我推荐,资源用完即显式释放,或者利用资源池来尽量重用。

Java 平台目前在逐步使用 java.lang.ref.Cleaner 来替换掉原有的 finalize 实现。Cleaner 的实现利用了幻象引用(PhantomReference),这是一种常见的所谓 post-mortem 清理机制,它比 finalize 更加轻量、更加可靠。


六、总结

这是大部分都来自极客时间杨老师的讲解,自己整理一下自己可以看懂的部分,加上了一些例子为了后面学习和复习使用,如果对你有用点个赞呗!!!

相关文章
|
2月前
|
存储 缓存 安全
除了变量,final还能修饰哪些Java元素
在Java中,final关键字不仅可以修饰变量,还可以用于修饰类、方法和参数。修饰类时,该类不能被继承;修饰方法时,方法不能被重写;修饰参数时,参数在方法体内不能被修改。
34 2
|
2月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
142 4
|
2月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
89 2
|
2月前
|
Java
final 在 java 中有什么作用
在 Java 中,`final` 关键字用于限制变量、方法和类的修改或继承。对变量使用 `final` 可使其成为常量;对方法使用 `final` 禁止其被重写;对类使用 `final` 禁止其被继承。
42 0
|
3月前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
47 3
|
3月前
|
存储 安全 Java
了解final关键字在Java并发编程领域的作用吗?
在Java并发编程中,`final`关键字不仅用于修饰变量、方法和类,还在多线程环境中确保对象状态的可见性和不变性。本文深入探讨了`final`关键字的作用,特别是其在final域重排序规则中的应用,以及如何防止对象的“部分创建”问题,确保线程安全。通过具体示例,文章详细解析了final域的写入和读取操作的重排序规则,以及这些规则在不同处理器上的实现差异。
了解final关键字在Java并发编程领域的作用吗?
|
3月前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
39 5
|
3月前
|
存储 安全 Java
java基础面试题
java基础面试题
38 2
|
3月前
|
存储 安全 Java
了解final关键字在Java并发编程领域的作用吗?
了解final关键字在Java并发编程领域的作用吗?
|
2月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
下一篇
开通oss服务