谈谈final、finally、 finalize有什么不同?
final是用来修饰类,方法,变量,并具有不同的涵义
修饰类: 代表此类不可以继承扩展
修饰方法:代表此方法不可以重写
修饰变量:变量不可以修改
fianlly则是保证Java代码必须被执行的一种机制
我们使用try-finally或者try-catch-finally来进行类似1.关闭JDBC连接,2.保证unlock锁等动作
finalize则是java.lang.Object的一个方法,保证对象在被垃圾收集前完成特定资源的回收,所以称为java GC的阻碍,成为了特等公民,其次,finalize还可以吞掉Throwable,导致程序检查不出错误也无法运行,现在已经被定义为Old方法,
性能、并发、对象生命周期或垃圾收集基本过程等方面的理解
**final:**只读,不能修改,防止某些使用者更改API,这是保证功能的必要手段 。final修饰的变量,也可以有效防止错误赋值引起的错误
try {
// do something
System.exit(1);
} finally{
System.out.println(“Print from finally”);
}
此代码段的finally{}不会被执行,这是特例(也有原因,是因为try方法分明能够执行)
更进一步,final并不等于immutable
final List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("world");
List<String> unmodifiableStrList = List.of("hello", "world");
unmodifiableStrList.add("again");
在这里final只是约束strList这个引用不能被赋值,而它的对象行为毫无影响。
如果要定义某个类变为immutable类
需要以下几点:
1.需要将class定义final类
2.将所有成员变量定义为final和private,并且不要实现setter方法
3.通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值,这是防御措施,因为你不知道赋值会不会被人修改
4.如果确定需要实现getter方法,或者其他会返回内部的方法,使用copy-on-write原则,创建私有的copy
在并发中经常使用
我们可以用java.lang.ref.Cleaner 来替换掉原有的 finalize 实现
常用的幻象引用,post-mortem的清理机制
每个cleaner都是独立的,有自己独有的清理路线,不会造成死锁的问题
mysql jdbc driver中的jdbc connecter-j,利用了幻象引用机制。
幻象引用也可以进行类似链条式依赖关系的动作,进行总量控制的场景,保证只有连接被关闭,相应资源被回收,连接池才能创建新的连接。