final
关键字来 明确表示
代码的语义和逻辑意图 final
,明确表示不允许重写或继承 final
修饰参数或变量,能够避免意外赋值而导致的编程错误 final
变量产生了某种程度的 不可变
(immutable)的效果,可以用于保护只读数据 JVM
足够智能,
final
对性能的影响,在大部分情况下,都没有必要考虑
,应用程序更应该关注的是 语义
Java目前没有 原生的immutable支持
// final只能约束strList这个引用不可以被赋值,但strList对象本身的行为是不受影响的 final List<String> strList = new ArrayList<>(); strList.add("Hello"); strList.add("World"); // since 9 List<String> unmodifiableStrList = List.of("Hello", "world"); // throw java.lang.UnsupportedOperationException unmodifiableStrList.add("again");
final class
private final
,并且不要实现 setter
方法 getter
,使用 copy-on-write
原则 try-finally
和 try-catch-finally
try-with-resources
(JDK 7引入) try { System.exit(-1); } finally { // 不会执行 System.out.println("Print from finally"); }
java.lang.Object
中的一个 protected
方法 JDK 9
中已经被标记为 @Deprecated(since="9")
finalize()
何时会执行,执行的结果是否符合预期
finalize
方法,会导致对象回收呈现 数量级
上的变慢(40~50倍) finalize
方法的对象是 特殊公民
,JVM需要对它们进行额外的处理 finalize
本质上成为了 快速回收的阻碍者
System.runFinalization()
同样是不可预测的 finalize
会拖慢GC,导致 大量对象堆积
,有可能导致 OOM
finalize
去承担释放资源的主要职责 finalize
会 掩盖资源回收时的出错信息
// Throwable被生吞 private void runFinalizer(JavaLangAccess jla) { ... try { Object finalizee = this.get(); if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { jla.invokeFinalize(finalizee); // Clear stack slot containing this variable, to decrease // the chances of false retention with a conservative GC finalizee = null; } } catch (Throwable x) { } super.clear(); }
java.lang.ref.Cleaner
替换掉原有的 finalize
实现 Cleaner
的实现利用了 幻象引用
(Phantom Reference) Cleaner
比 finalize
更加 轻量
,更加 可靠
Cleaner
的操作都是 独立
的,都有 自己的运行线程
,可以 避免意外死锁
等问题 Cleaner
或者 幻象引用
改善的程度依然是有限的 Cleaner
适合作为 最后的保证手段
,而 不能完全依赖
Cleaner
进行资源回收 public class CleaningExample implements AutoCloseable { // A cleaner, preferably one shared within a library private static final Cleaner cleaner = Cleaner.create(); // State定义为static,为了避免由于普通的内部类隐含对外部对象的强引用,而导致外部对象无法进入幻象可达的状态 static class State implements Runnable { State() { // initialize State needed for cleaning action } @Override public void run() { // cleanup action accessing State, executed at most once } } private final State state; private final Cleaner.Cleanable cleanable; public CleaningExample() { this.state = new State(); this.cleanable = cleaner.register(this, state); } @Override public void close() { cleanable.clean(); } }