如果该对象的构造函数是异常,是否有使用finalize()
清除对象的详细信息。
当调用此方法时,出了名的错误定义。根据手册:
Java编程语言不保证哪个线程会 为任何给定对象调用finalize方法。这是有保证的, 但是,调用finalize的线程不会持有任何 调用finalize时,用户可见的同步锁定。如果 finalize方法抛出未捕获的异常,例外是 忽略并终止该对象的终结。
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29
我无法以这种方式触发finalize方法。有没有人知道它是不是被调用了,或者是否在某些情况下在构造函数初始化对象后调用(这是异常)。
我问这个是因为我有一个不能清理两次的物体。我试图了解在抛出异常之前清理是否安全,或者我是否必须为finalize()
留下标记以有效地跳过并且什么都不做。
答案 0 :(得分:11)
我的测试表明它可以
public class Test1 {
Test1() {
throw new RuntimeException();
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalized");
}
public static void main(String[] args) throws Exception {
try {
new Test1();
} catch (RuntimeException e) {
e.printStackTrace();
}
System.gc();
Thread.sleep(1000);
}
}
打印
java.lang.RuntimeException
at test.Test1.<init>(Test1.java:13)
at test.Test1.main(Test1.java:24)
finalized
它位于Java HotSpot Client VM 1.7.0_03
上答案 1 :(得分:10)
根据JLS的12.6.1. Implementing Finalization部分:
对象o在其构造函数调用了o上的Object的构造函数并且该调用已成功完成(即不抛出异常)之前无法终结。
如果构造函数在对象构造函数完成后抛出异常,那么您的对象应该是可终结的,因此仍然可以调用finalize()
。
在12.5. Creation of New Class Instances部分中逐步介绍对象构造,这是一个很好的例子,可以准确显示何时调用Object构造函数。
答案 2 :(得分:1)
更清楚地证明:
public class Test1 {
public static class LifeBoat extends RuntimeException
{
private Test1 passenger;
public Test1 getPassenger(){return passenger;}
public LifeBoat(Test1 passenger){this.passenger=passenger;}
}
Test1() {
super(); //once this is finished, there is an Object to GC per JLS 12.6.1.
throw new LifeBoat(this);
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalized");
}
public static void main(String[] args) throws Exception {
try {
new Test1();
} catch (LifeBoat e) {
Test1 obj;
obj=e.getPassenger();
System.out.println(obj);
}
System.gc();
Thread.sleep(1000);
}
}
打印
java.lang.RuntimeException
at test.Test1.<init>(Test1.java:13)
at test.Test1.main(Test1.java:24)
test.Test1@6dc8f3cd
finalized