第一,final
final 可以用来修饰类,方法,变量,分别有不同的意义,final修饰的class代表不可以继续扩展,final修饰的变量是不可以修改,而final的方法也是不可以被重写。
很多文章和书籍中会介绍在特定的场景final可以提高性能,其实很多类似的结论都是基于假设得出的。比如现代高性能jvm(如HotSpot)判断内联未必依赖final的提示,要相信JVM是非常智能的。类似的,final字段对性能的影响,大部分情况下,并没有考虑的必要。程序最好是体现它的语义目的,在日常开发中,除非有特别考虑,不然最好不要指望这种小技巧带来的所谓性能好处,因为这是和JVM的实现很相关的,未经验证比较难以把握。如果查阅相关资料,千万别忘了去验证一下。
需要注意的是:final并不等同于immutable。比如下面的这段代码:
immutable在很多场景是非常棒的选择,某种意义上说,java语言目前并没有原生的不可变支持,如果要实现immutable的类,我们可以做到:
1,讲class自身声明为final。2,将所有成员变量定义为private和final,并且不要实现set方法。3,通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值。4,如果需要实现get方法,使用copy-on-write原则,创建私有的copy。
关于set/get方法很多人喜欢直接使用IDE一次全部生产,建议最好是需要用时再生成。
什么是深度拷贝和浅度拷贝?浅度拷贝指向的是同一个内存,而深度拷贝是增加了一个新的内存,不会影响到原来的内存。
匿名内部类,访问局部变量时,局部变量为啥要用final来修饰?这个因为Java inner class实际会copy一份,不是去直接使用局部变量,final可以防止出现数据一致性问题
第二,finally
finally则是java保证重点代码一定被执行的一种机制。我们可以使用try-finally或者try-catch-finally来进行类似关闭JDBC连接,保证unlock锁等动作。
第三,finalize
finalize是基础类java.lang.Object的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize机制现在已经不推荐使用,并且在jdk9开始被标记为deprecated.因为finalize被设计成在对象被垃圾收集前调用,这就意味着实现了finalize的对象时个特殊公民,JVM要对它进行额外处理。finalize本质上成为快速回收的阻碍者,拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致OOM的原因。
有什么机制可以替换finalize?目前逐步使用java.lang.ref.Cheaner来替换掉原有的finalize的实现。Cheaner的实现是利用了幻象(虚)引用。这是一种常见的所谓post-mortem清理机制。我们可以保证对象被彻底销毁前做一些类似资源回收的工作,比如关闭文件描述符(操作系统有限资源),它比finalize更加轻量,更加可靠。吸取了finalize里的教训,每个Cleaner操作都是独立的,它有自己的运行线程,所以可以避免死锁。注意,从可预测的角度来判断,cheaner或者幻象引用改善的程度任然是有限的,如果由于种种原因导致幻象引用堆积,同样会出现问题,所以,Cleaner适合作为一种最后的保证手段,而不是完全依赖Cheaner进行资源回收。
我是温驭臣,一个Android开发者,以上是我的简单总结,如果有缺陷,希望在评论区看到您的补充。