谈谈final、finally、 finalize有什么不同?

《Java核心技术面试精讲–杨晓峰》学习笔记目录

文章目录

      • 简单来说,三者仅是长得像。
      • 详细的讲
        • final
          • 匿名内部类与final
          • finnal 与 static
          • 修改final修饰内容的方式
          • 实现不可变(immutable)类
          • 为什么 String 会被设计成不可变?
        • finally
          • System.exit(1)
        • finalize
          • 为什么不建议使用 finalize
          • Cleaner
      • 扩展
        • 浅拷贝与深拷贝
        • 防御性拷贝(暂)
        • CopyOnWrteArrayList(暂)
        • java 的clone方法(暂)

简单来说,三者仅是长得像。

  • final 修饰符,修饰类时不可被继承,修饰方法时不可被重写,修饰变量时不可被修改;final 修饰引用类型时,只能防止引用(地址值)被修改,但不能防止对象中的属性被修改
  • finally try…catch…finally 中使用,进行类似关闭 JDBC 连接、保证 unlock 锁等动作。jdk1.7后许多类或者接口都实现了AutoCloseable,建议使用try…with…resources。
  • finalize 是Object的方法,用于在垃圾回收之前关闭特定资源。但有许多限制,不建议使用

详细的讲

final

匿名内部类与final
  1. 匿名内部类引用外部类的成员变量通过外部类的引用来访问。因而内部类中对任何外部类成员变量的修改都会真实地反应到外部类实例本身,所以不需要用final来修饰它
  2. 在匿名内部类里面尝试改变外部基本类型的变量的值的时候,或者改变外部引用变量的指向的时候,并不会影响到外部的变量。所以需要加final限制。
  3. java8开始,可以不加final修饰符,由系统默认添加。java将这个功能称为:Effectively final(A variable or parameter whose value is never changed after it is initialized is effectively final) 功能。
finnal 与 static
  • static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块
  • 被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
  • static final用来修饰成员变量和成员方法,可以理解为“全局变量”
    对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
    对于方法,表示不可覆盖,并且可以通过类名直接访问。
  • static代码块
    static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
修改final修饰内容的方式

setAccessible

实现不可变(immutable)类

声明为final类,成员为private final,构造函数中做深拷贝(见扩展),无set方法,在get方法中对于可变类要做防御性拷贝。

为什么 String 会被设计成不可变?

finally

System.exit(1)
finally中的代码不会被执行,因为 JVM 已经被关闭了。
try {
  // do something
  System.exit(1);
} finally{
  System.out.println(“Print from finally);
}

finalize

为什么不建议使用 finalize
  • finalize的调用时间不确定——导致资源存在延迟释放的现象,资源在内存中越来越多会导致内存空间不够,此时进程会主动从内存换出到外存,即挂起
  • finalize有可能不会被调用,那么资源永远也不会被释放,那么存在两个进程A和B,A持有资源N(不被释放),申请资源M;B持有资源M(不被释放),申请资源N,因此导致死锁的发生
  • 在使用finalize时存在"诈尸"的情况,所以垃圾回收器只能在每次调用完finalize()之后再次去检查该对象是否还处于失效状态。这无形中又增加了JVM的开销,即影响性能。
Cleaner
  • Cleaner 实现了 AutoCloseAble 接口

JDK 自身使用的 Cleaner 机制仍然是有缺陷的,你有什么更好的建议吗?
1,临时对象,使用完毕后,赋值为null,可以加快对象的回收
2,公用资源对象,比如数据库连接,使用连接池
3,native调用资源的释放,比如一个进程初始化调用一次,退出调用一次,这类场景可以考虑使用cleaner
4,对尽量try-finally中完成资源的释放,即使用完毕就释放,最小化的使用,下次使用在申请。
5,可以使用钩子进行程序的正常退出清理操作。

扩展

浅拷贝与深拷贝

  • 两者在基本类型上没有区别。但在引用类型上,浅拷贝会改变被拷贝对象,而深拷贝不会。
  • 一个类实现深拷贝的功能有两种方式;要么实现Clone~接口,然后在clone方法里面进行拷贝;要是实现序列化,先把对象写到输入流里面,然后在读出来对象,这样就是一个新的对象了。

防御性拷贝(暂)

留待有时间再看:https://blog.csdn.net/qq_41204349/article/details/92443171

CopyOnWrteArrayList(暂)

适合读多写少的场景,写的时候会复制,并发安全的ArrayList。改变lsit内容的地方用了reentrantlock加锁操作,有一定开销,但是线程安全。

java 的clone方法(暂)

https://blog.csdn.net/qq_33314107/article/details/80271963

参考文献:
https://www.cnblogs.com/ggzhangxiaochao/p/10640905.html
https://blog.csdn.net/zjy15203167987/article/details/80644156
https://www.zhihu.com/question/21395848

你可能感兴趣的:(谈谈final、finally、 finalize有什么不同?)