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();
}
}