final “最终的”的意思,在Java中又有意为常量的意思,也就是被final修饰的只能进行一次初始化!
加载:final可以在编译(类加载)时初始化,也可以在运行时初始化,初始化后不能被改变。
可修饰:类、内部类、方法、成员变量、局部变量、基本类型、引用类型。
1、 final 修饰基本类型:值不能被修改;
2、final 修饰引用类型:引用不可以被修改也就是说不能指向其他对象,但是该引用的对象内容可以被修改;
3、final 修饰 方法,方法不可以重写,但是可以被子类访问 【前提:方法不是 private 类型】。
4、final 修饰 类,类不可以被继承。
finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。
finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
对于 finally,明确知道怎么使用就足够了。需要关闭的连接等资源,更推荐使用 Java 7 中添加的 try-with-resources 语句,因为通常 Java 平台能够更好地处理异常情况,编码量也要少很多,何乐而不为呢。
另外,我注意到有一些常被考到的 finally 问题(也比较偏门),至少需要了解一下。比如,下面代码会输出什么?
try {
// do something
System.exit(1);
} finally{
System.out.println(“Print from finally”);
}
上面 finally 里面的代码可不会被执行的哦,这是一个特例。
finalize是方法名。finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9 开始被标记为 deprecated。
对于 finalize,我们要明确它是不推荐使用的,业界实践一再证明它不是个好的办法,在 Java 9 中,甚至明确将 Object.finalize() 标记为 deprecated!如果没有特别的原因,不要实现 finalize 方法,也不要指望利用它来进行资源回收。
为什么呢?简单说,你无法保证 finalize 什么时候执行,执行的是否符合预期。使用不当会影响性能,导致程序死锁、挂起等。
通常来说,利用上面的提到的 try-with-resources 或者 try-finally 机制,是非常好的回收资源的办法。如果确实需要额外处理,可以考虑 Java 提供的 Cleaner 机制或者其他替代方法。
上面简单介绍了 finalize 是一种已经被业界证明了的非常不好的实践,那么为什么会导致那些问题呢?
finalize 的执行是和垃圾收集关联在一起的,一旦实现了非空的 finalize 方法,就会导致相应对象回收呈现数量级上的变慢,有人专门做过 benchmark,大概是 40~50 倍的下降。
因为,finalize 被设计成在对象被垃圾收集前调用,这就意味着实现了 finalize 方法的对象是个“特殊公民”,JVM 要对它进行额外处理。finalize 本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能被回收。
有人也许会问,我用 System.runFinalization() 告诉 JVM 积极一点,是不是就可以了?也许有点用,但是问题在于,这还是不可预测、不能保证的,所以本质上还是不能指望。实践中,因为 finalize 拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致 OOM 的原因。
从另一个角度,我们要确保回收资源就是因为资源都是有限的,垃圾收集时间的不可预测,可能会极大加剧资源占用。这意味着对于消耗非常高频的资源,千万不要指望 finalize 去承担资源释放的主要职责,最多让 finalize 作为最后的“守门员”,况且它已经暴露了如此多的问题。这也是为什么我推荐,资源用完即显式释放,或者利用资源池来尽量重用。
finalize 还会掩盖资源回收时的出错信息。