JAVA面试点滴整理——全面剖析

final、finally、 finalize区别

2019-03-18  本文已影响0人  从林战士们
  1. 可以将方法或者类声明为final,明确告诉不可以被修改。如Java类库的一些基础类中相当一部分被声明为final class,这样做可以有效避免API使用者更改基础功能,同样也是保证平台安全的必要手段。
  2. 使用final修饰参数或者变量,也可以清楚地避免意外赋值导致的边城错误,甚至,有人明确推荐将所有方法参数、本地变量、成员变量声明成final。
  3. Final变量产生了某种程度的不可变(immutable)的效果,所以可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值final变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。
  4. Final 也许会有性能的好处, 可以利用final帮助JVM将方法进行内联,可以改善编译器进行条件编译的能力等等。但这些仅仅是基于假设得出的结论,比如JVM(Hotspot)判断内联未必依赖final的提示,以及还有很多类似的,final字段对性能的影响,大部分情况可以忽略。
  5. 在实际开发场景中,除非特别考虑性能环节,不然最好不要指望这种小技巧带来的所谓性能好处,程序本身就应该体现它的语义目的。
  1. 明确知道如何使用finally
  2. 需要关闭的链接等资源,可以使用Java7中添加的try-with-resources语句,通常情况下Java平台本身可以更好的处理异常情况,编码量也要少很多
  1. 明确知道已经不推荐使用,并且Java9将Object.finalize()标记为deprecated,
  2. 不要指望利用finalize来资源回收,因为我们无法保证finalize什么时候执行,执行的是否符合预期,使用不当还会影响性能,导致程序死锁、挂起等。
  1. 为啥导致不好用?finalize的执行是和垃圾收集关联在一起的,一旦实现了非空的finalize方法,就会导致相应对象回收呈现数量级上的变慢,benchmark显示大概会有40~50倍的下降。
  2. finalize被设计成灾对象被垃圾回收前调用,就是意味着实现了finalize的方法的对象是“特殊公民”,JVM要怼它进行额外处理。finalize本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能被收回
  3. System.runFinalization()告诉JVM积极一点,是不是就可以满足快速垃圾回收,但这种方式本身是不可预测情况发生的,并且不能保证,所以在本质上不能指望这么操作以解决问题,现实环境中,由于finalize拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致OOM的原因
  4. 不要指望利用finalize来资源回收,因为我们无法保证finalize什么时候执行,执行的是否符合预期,使用不当还会影响性能,导致程序死锁、挂起等。

  1. 注意1.final不是immutable(不可变)
  final List<String> strList = new ArrayList<>();
  strList.add(“hello”);
  strList.add(“world”);
  List<String> unmodifiableStrList = List.of(“hello”, “world”);
  unmodifiableStrList.add(“agin”);
  1. 将class自身声明为final,这样别人就不能扩展来绕过限制了
  2. 将所有成员变量定义为private和final,且不要实现setter方法
  3. 通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值,这是一种防御措施,因为这个环节无法确定输入对象不被其他人修改。
  4. 如果确实需要实现getter方法,或者其他可能会返回内部状态的方法,使用copy-on-write原则,创建私有的copy
  1. Cleaner的实现利用了幻象引用(PhantomReference)这是一种常见的post-mortem 清理机制,利用幻象引用和引用队列,我们可以保证对象被彻底销毁前做一些类似资源回收的工作,比如关闭文件描述符,这种方式比finalize更轻量、更加可靠一点
  2. 每个Cleaner的操作都是独立的,有自己的运行线程,这样也就避免意外死锁等问题
  3. 虽然如此,但Cleaner或者幻象引用改善的成仍然有限的,如果由于种种原因导致幻象引用堆积,同样会出现问题。所以Cleaner适合作为一种最后的保证手段,不能完全依赖
  4. 常见的使用幻象引用机制有MYSQL JDBC driver之一的mysql-connector-j,幻象引用也可以进行类似链条式依赖关系的动作,比如,进行总量控制的场景,保证只有连接被关闭,相应资源被回收,连接池才能创建新的连接

总结Summary

上一篇下一篇

猜你喜欢

热点阅读