2016-03-05 64 views
8

请考虑以下Java中的简单示例。通过调用new B(0)创建对象会发生什么?首先,在内存中创建一个类型为B的对象。然后,表达式1/n将抛出异常。但是,根据下面的Java规范(第12.6.1节),创建的对象将永远不会完成。那么我们是否会发生内存泄漏?在Java中,评估构造函数调用的参数时会发生什么情况会引发异常?

请注意,我不是问“构造函数是否可以抛出异常”,而是“如果构造函数在特定情况下抛出异常,会发生什么。”

对象o直到它的构造函数调用了o上的Object的构造函数并且该调用已成功完成(即,没有引发异常)才能被终结。

class A { 
    int n; 
    A(int n) { 
     this.n = n; 
    } 
} 

class B extends A { 
    B(int n) { 
     super(1/n); 
    } 
} 
+2

我认为“可定制的”指的是在对象被GCed时调用'finalize()',而不是*该对象是否会被GCed。 –

+3

可能的重复[可以构造函数在Java中引发异常?](http://stackoverflow.com/questions/1371369/can-constructors-throw-exceptions-in-java) – mawalker

+0

@DavidEhrmann正确。一个对象是否可以终结是很无关紧要的,因为几乎没有你应该使用终结器的场景。 – biziclop

回答

4

你引述的可达性和finalizability区分的部分:

每个对象的特征可以是两个属性:它可能是可达的,终结可达的,或无法访问,它也可以未定型,可定型或最终定型。

因此,一个对象可以独立地到达或不可到达,并且可终结或不可终结。

在你提到的Object构造从来没有运行,因此该对象不是终结,但OTOH构造已抛出异常,因此new结果给一个变量赋值不会发生,所以它是不可达的情况下。

所以没有内存泄漏。

+1

您可以使用'-verbose:gc'运行[这个小测试](http://pastebin.com/A5tMhAxw)来验证这一点。事实上,“失败”的情况下运行速度更快,清除内存的速度要快得多,这听起来只有在看到如何实现最终化,以及它如何阻止GC并减慢所有内容 – biziclop

相关问题