在Java中,当计算构造函数调用的参数抛出异常时会发生什么?
考虑下面Java中的简单示例。如果通过调用在Java中,当计算构造函数调用的参数抛出异常时会发生什么?,java,Java,考虑下面Java中的简单示例。如果通过调用new B(0)创建对象,会发生什么情况?首先,在内存中创建一个类型为B的对象。然后,表达式1/n将引发异常。但是根据下面的Java规范(§12.6.1),创建的对象永远不会最终确定。我们有内存泄漏吗 请注意,我不是在问“构造函数是否可以抛出异常”,而是在问“如果构造函数在特定情况下抛出异常会发生什么情况” 对象o在其构造函数调用o上对象的构造函数并且该调用已成功完成(即,在不引发异常的情况下)之前是不可终结的 您引用的部分区分了可达性和终结性: 每个对
new B(0)
创建对象,会发生什么情况?首先,在内存中创建一个类型为B的对象。然后,表达式1/n将引发异常。但是根据下面的Java规范(§12.6.1),创建的对象永远不会最终确定。我们有内存泄漏吗
请注意,我不是在问“构造函数是否可以抛出异常”,而是在问“如果构造函数在特定情况下抛出异常会发生什么情况”
对象o在其构造函数调用o上对象的构造函数并且该调用已成功完成(即,在不引发异常的情况下)之前是不可终结的
您引用的部分区分了可达性和终结性: 每个对象都可以由两个属性描述:它可以是可访问的、终结器可访问的或不可访问的,也可以是未终结的、可终结的或终结的 因此,对象可以是可访问的或不可访问的,也可以是可终结的或不可终结的 在您提到的例子中,
对象
构造函数从未运行过,因此该对象不可终结,但构造函数引发了异常,因此不会将新
结果赋值给变量,因此无法访问
因此没有内存泄漏。我认为“finalizable”指的是在对象被GCed时调用
finalize()
,而不是该对象是否会被GCed。可能与@davidermann完全相同。对象是否可终结在很大程度上是无关紧要的,因为几乎没有应该使用终结器的场景。@Davidermann:如果是,这将回答我的问题,但规范说:“在垃圾收集器回收对象的存储之前,Java虚拟机将调用该对象的终结器。”@兰塞尔说得很好。规范对此可能有点不清楚,但如果无法调用终结器,GC仍将继续。您可以使用-verbose:GC
运行以验证这一点。事实上,“失败”的情况运行得更快,清除内存的速度也更快,这听起来很奇怪,直到您了解如何实现终结,以及它如何支持GC和减慢一切
class A {
int n;
A(int n) {
this.n = n;
}
}
class B extends A {
B(int n) {
super(1/n);
}
}