[英]When objects in Java are partially initialized ( an exception occurs in the constructor )
我听说有可能写出这样的代码
SomeClass obj = null;
try {
obj = new SomeClass();
} catch ( Exception e ) {
...
}
...
if ( obj != null ) { // here it holds true
...
}
有人可以解释一下,如果我们假设构造函数SomeClass 可能会抛出一个异常,那么它是否可能以及在什么条件下?
另一个例子:
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
public class Sample{
static class A {
public static A s;
public A(Collection c) {
c.add(this);
s = this;
throw new RuntimeException();
}
}
@Test
public void testResource() throws Exception {
List l = new ArrayList();
A a = null;
try {
a = new A(l);
fail("Oops");
} catch (Throwable e) {
}
assertTrue(l.size() == 1);
assertNull(a);
assertNotNull(A.s);
assertNotNull(l.get(0));
}
}
这很有可能。
我不确定我理解你的问题,你自己已经回答了: 如果构造函数抛出异常,obj可能为null。
你当然可以编写这样的代码,它会编译并运行得很好。 但永远不会出现obj
被“部分初始化”的情况。 要么是,要么不会。 具体来说,如果此行抛出Exception
:
obj = new SomeClass();
然后,就obj
的值而言,就好像该行从未被执行过一样。 您在该行之前将obj
初始化为null
,因此如果抛出异常,则obj
仍将为null
。 在这种情况下,程序最后不会进入if
块。
或者,如果未抛出异常,则obj
将不再为null
,并且将执行最终if
块内的代码。
首先声明并初始化变量。
SomeClass obj = null;
在以下行中,您(1)创建一个新实例,(2)存储引用。
try {
obj = new SomeClass();
} catch ( Exception e ) {
...
}
现在我们假设,实例化(步骤1)失败并抛出异常:JVM将在下一个处理该异常的catch块中继续。 因此,步骤2将不会被执行,变量将保持其实际状态。
现在可能已经部分初始化了一个实例。 老实说,我不知道,那是JVM的内部。 但由于没有任何内容可以参考这个部分初始化的实例,所以下次将会使用gc'd。
这是完全可能的; 仔细观察:如果构造函数抛出异常, obj
仍然为null
。
如果SomeClass
构造函数抛出异常,则obj
将为NULL。
对我来说,即使在调用构造函数后,该对象仍为null:
public static void main(String[] args) {
TestCls cls = null;
try {
cls = new TestCls("");
} catch (Exception e) {
e.printStackTrace();
}
if(cls == null)
System.out.println("hi");
}
public TestCls(String str) throws Exception{
throw new Exception();
}
输出: -
java.lang.Exception
hi
at TestCls.<init>(TestCls.java:57)
at TestCls.main(TestCls.java:48)
结论 :如果class constructor
抛出Exception
则obj
将为NULL
。
构造函数可以抛出异常,就像Java中的任何其他调用一样。 例如,如果尝试在空引用上调用方法,它可能会抛出NullPointerException。 请考虑以下示例:
public class ConstructionTest {
static ConstructionTest obj;
public ConstructionTest() {
String s = null;
s.hashCode();
}
public static void main(String[] args) {
try {
obj = new ConstructionTest();
} catch ( Exception e ) {
System.err.println(e);
}
if ( obj != null ) {
System.err.println("Not Null");
} else {
System.err.println("Is Null");
}
}
}
由于s在构造函数中为null,因此抛出NullPointerException,因此将打印“Is Null”。 没有“部分构造的对象”的概念 - 当你在Java中使用new时,它既可以工作又可以获得新实例化的对象,或者它不起作用并且你得到了Exception。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.