当Java中的对象被部分初始化时(构造函数中发生异常)

时间:2011-05-06 10:11:17

标签: java

我听说可以写一些像这样的代码

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));
    }

}

7 个答案:

答案 0 :(得分:2)

很有可能。

我不确定我理解你的问题,你自己已经回答了:如果构造函数抛出异常,obj可能为null。

答案 1 :(得分:2)

你当然可以编写这样的代码,它会编译并运行得很好。但永远不会出现obj被“部分初始化”的情况。要么是,要么不会。具体来说,如果此行抛出Exception

obj = new SomeClass();

然后,就obj的值而言,就好像该行从未被执行过一样。您在该行之前将obj初始化为null,因此如果抛出异常,则obj仍为null。在这种情况下,程序最后不会进入if块。

或者,如果未抛出异常,则obj将不再是null,并且将执行最终if块内的代码。

答案 2 :(得分:2)

首先声明并初始化变量。

SomeClass obj = null;

在以下行中,您(1)创建一个新实例,(2)存储引用。

try {
   obj = new SomeClass();
} catch ( Exception e ) {
   ...
}

现在我们假设,实例化(步骤1)失败并抛出异常:JVM将在下一个处理该异常的catch块中继续。因此,步骤2将不会被执行,变量将保持其实际状态。

现在是可能部分初始化了一个实例。老实说,我不知道,那是JVM的内部。但由于没有任何内容可以参考这个部分初始化的实例,所以下次将会使用gc'd。

答案 3 :(得分:1)

这是完全可能的;仔细观察:如果构造函数抛出异常,obj仍然是null

答案 4 :(得分:1)

如果SomeClass构造函数抛出异常obj将为NULL。

答案 5 :(得分:0)

对我来说,即使在调用构造函数之后,对象也为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,则objNULL

答案 6 :(得分:0)

构造函数可以抛出异常,就像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时,它既可以工作,又可以获得新实例化的对象,或者它不起作用,你就会得到异常。