繁体   English   中英

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

[英]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抛出Exceptionobj将为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM