final、finally、 finalize有什么不同

Final可以用来修饰类、方法、变量,修饰类表示类不能被继承,修饰方法表示方法不能被重写(override),修饰变量表示变量不能被更改。

Finally是用来保证重要代码被执行的一种机制,我们可以用try-finally、try-catch-finally等来关闭sql链接,释放锁等

Finalize是Object的一个方法,他的设计目的是用来保证对象在垃圾回收前对特定资源被回收。JDK9已经被标记为deprecated

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

  • 我们将方法和类声明为final,意在告诉别人这些行为不可改的,保证逻辑的正确性、安全性
  • 使用final修饰参数或者变量,可以清楚的避免意外赋值导致的编程错误,甚至有人推荐将所有方法、局部变量、全局变量声明为final
  • final产生了某种程度的不可变(immutable)的效果,可以用于保护只读数据,在并发编程中,因为明确地不能再赋值final变量,有利于减少额外的同步开销,也可以省去一些防御性的拷贝的必要

对于finally知道怎么用就足够了,如果需要关闭资源,推荐使用jdk7提供的try-with-resources语句,因为通常java平台能够更好地处理异常情况,编码量也要少很多,何乐而不为呢。有以下几种情况finally不会被执行

  • System.exit(1)
  • 死循环
  • 线程被杀死

Finalize,我们明确不推荐使用的,java9已经标记deprecated,也不要指望利用它来进行资源回收。简单说,你无法保证finalize是么时候执行,执行的是否符合预期。使用不当会影响性能,导致程序死锁、挂起等

知识扩展

1.注意:final不是immutable

final List<String> strList = new ArrayList&lt;&gt;();

strList.add(“Hello”);

strList.add(“world”);

List<String> unmodifiableStrList
= List.of(“hello”, “world”);

unmodifiableStrList.add(“again”);

final只能约束strList这个引用不被修改,但是对象行为不受影响,添加、删除元素是正常的,如果我们真的希望对象本身是不可变的,需要类支持不可变的行为,List.of创建的是不可变的,add会抛出异常

如果要实现immutable类我们需要做到:

  • Class声明为final,这样别人就不能通过扩展绕过限制了
  • 所有成员变量定义为private和final,并且不要实现setter方法
  • 通常构造对象使用深度拷贝来初始化,而不是直接赋值,这是一种防御措施,因为你无法确定输入对象不被人修改。
  • 如果确定需要实现getter方法,或者其他可能会返回内部状态的方法,使用copy-on-write原则,创建私有的copy

关于setter和getter方法,很多人喜欢用IDE直接生成,建议最好是有需要是再实现

2. finalize真的那么不堪吗

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

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

视线中因为finalize拖慢了垃圾收集,导致大量对象堆积,也是一种典型的导致OOM的原因

我们要确保回收资源就是因为资源是有限的,垃圾收集时间的不可预测,可能会极大家具资源占用。这意味着消耗非常高的资源,这也是为什么推荐资源用完即显示释放或者利用资源池来尽量重用

Finalize会生吞异常,这也是大忌

3.有什么机制可以替换finalize吗

关注java.lang.ref.Cleaner,利用幻象引用,这是一种常见的所谓post-mortem清理机制,利用幻象引用和引用队列,我们可以保证对象被彻底销毁前做一些类似资源回收工作,他比finalize更加轻量、可靠

但是从可预测角度来判断,Cleaner或者幻象引用改善的程度仍然是有限的,由于种种原因导致幻象引用堆积,同样会出问题。所以Cleaner适合作为一种最后的保证手段,而不是完全依赖Cleaner进行资源回收,不然就再做一遍finalize噩梦。

Mysql
jdbc driver之一的mysql-connection-j 就是利用幻象引用机制。

copy-on-write原则参考:

https://www.cnblogs.com/lengender-12/p/7054896.html

http://ifeve.com/java-copy-on-write/

try-with-resources参考:

https://www.cnblogs.com/itZhy/p/7636615.html

    原文作者:天持
    原文地址: https://zhuanlan.zhihu.com/p/41581587
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞