final、finally、finalize的区别

284 阅读3分钟

我想吐槽的话:今天看了一道面试题,我是真的真的真的不知道为什么要把这三个家伙放在一起说,感觉真的没有一点关联,既然有题就解呗........

- final

final即最终的意思,其实我更喜欢叫他断子绝孙法(记得大一上课的时候,我的java导师说的)。final关键字可以用于修饰类、变量、方法。

当final修饰变量时,如final Object obj = new Object();则代表不可以将其他的值赋值给obj,即obj在final写下的一刻就会以强引用方式常驻内存中,gc也不会回收,除非程序结束或方法出栈这类对象地址已经没有引用可达的情况。若明确某一变量是一个一成不变的值,那就把它定义为final把,毕竟,定义为final让变量从RW(读写)模式修改为Only read(只读)模式,可以减少线程同步的开销。

当final关键字修饰方法时,则代表该方法在子类中不能被重写(override),即方法断子绝孙了.....

当final关键字修饰类时,即代表该类是最终类,不能被任何子类继承(这一刻,为这个类哭一哭把,他真的断子绝孙了)。jdk中常见的String就是用final关键字修饰的,final修饰类是一种保护类的手段,多用于第三方框架中,防止他人对框架继续修改而出现安全问题,这在某种意义上是包装平台安全的手段。

- finally

finally则是运用与try...cache语句中,用于保证代码一定执行的手段(常用于关闭流、关闭资源等,若finally中有返回值,会影响返回的数据,具体可以查看我的《聊一聊java中的异常》这一篇)。

- finalize

finalize则是Object类下的一个方法,在java中,所有的类都是继承自Object类的,因此,任何类都可以重写finalize方法以实现自己需要的业务逻辑。而主要作用就是finalize方法会在gc时候调用,用于释放一些必要资源但是,但是,但是 finalize在jdk9+就不推荐使用了,并且将该方法标记为deprecated。为什么呢?一看该机制不是挺好的吗?其实,java平台流行的主要原因就有自动垃圾回收,我们日常使用java平台除非是很大的项目,往往很少考虑到内存对程序的影响,毕竟内存可以自动回收(C++的同学哭了)。因此,若一个类重写类finalize方法并在方法体中实现类自己的逻辑,无疑将finalize机制与GC绑定在了一起,即该机制影响了gc周期,甚至造成OOM,明明空间已经可以回收了,但是由于finalize机制的存在,导致需要先执行finalize方法之后才能回收资源,所以gc周期被很大程度的拉长了。并且,我在测试中发现,对于uncheck类型的异常,若不使用try...cache语句进行捕获,居然不会打印堆栈(具体为什么还望大佬指点)。

目前,也有许多替换finalize的方案,如Cleaner、AutoCloseable等(先挖个坑吧)。 还有就是,finalize有一个较大的bug(居然可以让即将死去的对象活过来),其实具体操作就是把自己this赋值给其他变量,那么内存地址可达,对象就不会被回收,即通过如下方式

private static MyInterfaceImpl myInterface;

    @Override
    protected void finalize() throws Throwable {
        myInterface = this;
    }