很多编程语言都存在两个或以上相似关键字的情况。初次接触编程的人可能会对此产生疑惑。但对于稍有经验的人,即使无法即兴说一段教科书般的解释,他们心里也是非常清楚这些关键字的差别的。因为真的很简单。
Java中的“final”、“finally”、“finalize”就是一组相似的关键字。
final
“final”表示不可修改。它可以用来修饰类、方法、变量。
-
final 修饰类,表示该类不可以被继承;
-
final 修饰方法,表示该方法不可以被重写(override);
-
final 修饰变量,表示该变量不可以被修改
-
如果变量是原始数量类型,如 int、long、boolean,则表示该变量的值不可以被修改
-
如果变量是引用类型,则表示该变量只能表示已声明赋予它的对象,不能指向其它对象;但与目标对象内部数据是否可修改无关。
例,final A a = myA;,a 只能表示 myA 这个实例,但是对 myA 中属性 x 的修改不受此处的 final 限制
-
一个必须使用 final 的常见的场景
匿名内部类访问局部变量时,内部类会 copy 一份这个局部变量;所以为了防止出现数据不一致的情况,需要将该局部变量声明为 final
合理使用 final
final 的正确用法就是其语义。即,从业务或实现角度而言,某些类、方法或变量是不允许被修改的,有必要用 final 来保护它们,那就可以用 final。
虽然“不可被修改”这个特性或许可以稍微提高某些场景的性能,但这类“小技巧”通常是未经验证过推测。
另外,JVM 是比较智能的,这类小技巧必要性很小,不要在日常开发中使用。
程序最好体现其语义目的,而不应被性能目的绑架到“面目全非”。
finally
“finally”是 Java 保证重点代码一定要被执行的一种机制。它以 try-finally 或 try-catch-finally 的形式使用。
如,在 finally 语句块中关闭 JDBC 连接、关闭某些同步锁等。
当然,对于实现了 java.lang.AutoCloseable 接口的对象,try-with-resources 的写法也是非常值得使用的资源释放形式。
Java代码
-
BufferedReader br = new BufferedReader(new FileReader(path));
-
try {
-
return br.readLine();
-
} finally {
-
if (br != null) br.close();
-
}
Java代码
-
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
-
return br.readLine();
-
}
特例:无法被执行的 finally
Java代码
-
try {
-
...
-
System.exit(1);
-
} finally {
-
...
-
}
finalize
“finally”是 java.lang.Object 类的一个方法。垃圾收集器会调用该方法以保证对象被收集前完成特定资源的回收。
这种机制已经不推荐使用,JDK 9 已经将其标记为 deprecated。
如果 try-finally 无法满足需求,可以考虑用 Cleaner 机制。
Cleaner 机制中,每个 Cleaner 的操作都是独立的,有自己的运行线程,可以避免意外死锁等问题。但无法避免幻象引用堆积。
Java代码
-
public class CleaningExample implements AutoCloseable {
-
// A cleaner, preferably one shared within a library
-
private static final Cleaner cleaner = <cleaner>;
-
-
static class State implements Runnable {
-
State(...) {
-
// initialize State needed for cleaning action
-
}
-
-
public void run() {
-
// cleanup action accessing State, executed at most once
-
}
-
}
-
-
private final State;
-
private final Cleaner.Cleanable cleanable
-
-
public CleaningExample() {
-
this.state = new State(...);
-
this.cleanable = cleaner.register(this, state);
-
}
-
-
public void close() {
-
cleanable.clean();
-
}
-
}