final、finally、 finalize有什么不同?

文章目录

  • 问题:final、finally、 finalize有什么不同?
  • 典型回答
    • final
    • finally
    • finalize
  • 考点分析&知识拓展
    • 零碎
    • 注意,final并不等同immutable(不可变)。
    • 代替finalize的机制
      • 补充
        • 还是尽量避免使用Finalize和Cleaner机制。
        • 参考文献

问题:final、finally、 finalize有什么不同?

典型回答

final

final可以用来修饰类、方法、变量,分别具有不同意义。

final修饰类代表不可以被继承扩展。

final修饰方法代表不可以重写(override)。

final修饰变量代表变量是不可以修改的。

finally

finally则是Java保证重点代码一定要被执行的一种机制。

使用try-finally或try-catch-finally来进行类似关闭JDBC连接、保证unlock锁等动作。

finalize

finailize是基础类java.lang.Object的一个方法。

它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。

finalize机制现已不推荐使用,且在JDK9开始被标记为deprecated。

因为你无法保证finalize什么时候执行,执行的是否符合预期。使用不当会影响性能,导致程序死锁、挂起等。

考点分析&知识拓展

零碎

推荐使用final关键字来明确我们代码的语义、逻辑意图。如将方法或类声明为final,明确告知别人,这些行为是不允许修改的。

final字段对对性能的影响(提升),大部分情况下没有考虑的必要。

finally了解如何使用就好了。需要关闭的连接等资源,更推荐使用Java7中添加的try-with-resources语句,Java平台能更好的处理异常,编码量更少。

通常来说,利用try-with-resources或者try-finally机制,是非常好的回收资源的方法。如何确实需要额外处理,可以考虑Java提供的Cleaner机制或其他代替方案。

资源用完即显式释放,或者利用资源池来尽量重用。

注意,final并不等同immutable(不可变)。

如下:

final List strList = new ArrayList<>();
strList.add("Hello");//可以修改添加
strList.add("world");
List unmodifiableStrList = List.of("hello", "world");
unmodifiableStrList.add("again");//运行时会抛出异常

final只能约束strList这个引用不可以被赋值,但strList对象行为不被final影响。如果我们真希望对象本身是不变的,那么需要相应的类支持不可变的行为。如上,List.of方法创建的本身就是不可变的List。

Immutable 在很多场景是非常棒的选择,某种意义上说,Java 语言目前并没有原生的不可变支持,如果要实现 immutable 的类,我们需要做到:

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

代替finalize的机制

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

吸取了finalize里的教训,每个Cleaner的操作都是独立的,它有自己的运行线程,所以可以避免意外死锁等问题。

Cleaner 或者幻象引用改善的程度仍然是有限的,如果由于种种原因导致幻象引用堆积,同样会出现问题。所以,Cleaner 适合作为一种最后的保证手段,而不是完全依赖Cleaner 进行资源回收。

补充

还是尽量避免使用Finalize和Cleaner机制。

从Java 9开始,Finalizer机制已被弃用,但仍被Java类库所使用。 Java 9中 Cleaner机制代替了Finalizer机制。 Cleaner机制不如Finalizer机制那样危险,但仍然是不可预测,运行缓慢并且通常是不必要的。

那该怎么做?为对象封装需要结束的资源(如文件或线程),而不是为该类编写Finalizer和Cleaner机制?让你的类实现AutoCloseable接口即可,并要求客户在在不再需要时调用每个实例close方法,通常使用try-with-resources确保终止,即使面对有异常抛出情况。

Finalize、Cleaner机制的合法用途:

  • 作为一个安全网。以防资源的拥有者忽略了它的close方法。
  • 终止非关键的本地资源。
  • 即使是这样,也要当心不确定性和性能影响。

参考文献

https://www.cnblogs.com/IcanFixIt/p/8133798.html

你可能感兴趣的:(Java,基础)