
Java 中 finalize() 是受保护的实例方法,子类重写时会完全覆盖父类实现;System.gc() 触发的是当前对象实际类型的 finalize(),而非逐级调用父类版本——除非显式调用 super.finalize(),而 Object.finalize() 本身为空实现,无实际作用。
java 中 `finalize()` 是受保护的实例方法,子类重写时会完全覆盖父类实现;`system.gc()` 触发的是当前对象实际类型的 `finalize()`,而非逐级调用父类版本——除非显式调用 `super.finalize()`,而 `object.finalize()` 本身为空实现,无实际作用。
在 Java 中,finalize() 方法定义于 java.lang.Object 类中,其默认实现为空方法体(JDK 8 及之前)或直接抛出 UnsupportedOperationException(JDK 9+ 引入的弃用机制)。当子类(如 Person)重写该方法时,遵循的是标准的方法重写(Override)语义:JVM 在运行时根据对象的实际类型(runtime type)动态绑定到对应的 finalize() 实现,不会自动链式调用父类版本。
以您提供的代码为例:
public class Person {
int age;
String name;
@Override
public void finalize() throws Throwable {
System.out.println("Garbage collected --->" + this);
}
}
当 p = null; System.gc(); 执行后,若 Person 实例被垃圾回收器选中,JVM 仅调用 Person.finalize() —— 这是唯一被触发的方法。Object.finalize() 并不会被隐式调用,除非您在 Person.finalize() 内显式添加:
@Override
public void finalize() throws Throwable {
try {
System.out.println("Garbage collected --->" + this);
} finally {
super.finalize(); // 显式调用,但 Object.finalize() 无实质逻辑
}
}
⚠️ 需特别注意以下几点:
- finalize() 已自 Java 9 起被标记为 @Deprecated,Java 18 开始默认禁用,并将在未来版本中彻底移除。官方推荐使用 Cleaner 或 PhantomReference 替代资源清理逻辑。
- 不可依赖 System.gc() 的执行时机与次数:它仅是建议 JVM 执行 GC,不保证立即回收,也不保证 finalize() 被调用(尤其在现代 GC 算法下,finalize() 可能永远不执行)。
- 重写 finalize() 存在严重风险:可能引发性能瓶颈、死锁(如在 finalize() 中获取锁)、对象复活(resurrection),且无法保证调用顺序与线程安全性。
✅ 正确实践建议:
// ✅ 推荐:使用 try-with-resources 或显式 close()
public class Person implements AutoCloseable {
private boolean closed = false;
@Override
public void close() throws Exception {
if (!closed) {
System.out.println("Explicit cleanup for " + this);
closed = true;
}
}
}
// 使用示例
try (Person p = new Person()) {
// use p
} // 自动调用 close()
总之,Person.finalize() 被调用,并非因为“父类和子类都被调用”,而是因为重写机制决定了子类实现完全替代父类实现;Object.finalize() 的空实现也印证了无需额外调用。请尽快迁出 finalize(),拥抱更可靠、可预测的资源管理模型。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











