开发者

When objects in Java are partially initialized ( an exception occurs in the constructor )

I've heard that it is possible to write some code like this

SomeClass obj = null;

try {
    obj = new SomeClass();
} catch ( Exception e ) {
...
}
...
if ( obj != null ) { // here it holds true
...
}

Can somebody please explain, is that possible at all and under what conditions if we assume that constructor SomeClass may throw an Exception?

Another example:

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;

        pub开发者_开发百科lic 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));
    }

}


First you declare and initialize a variable.

SomeClass obj = null;

In the following lines you (1) create a new instance and (2) store the reference.

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

Now we assume, the instantiation (Step 1) fails and throws an exception: the JVM will continue in the next catch block that handles that exception. So step 2 will not be executed and the variable will keep its actual state.

Now is is possible that an instance has been initialized partially. Honestly, I don't know, that's JVM internal. But as nothing holds a reference to this partially initialized instance, it will be gc'd on the next occasion.


It's quite possible.

I'm not sure I understand your question though, you've answered it yourself: if the constructor throws an exception, obj could be null.


You can certainly write code like that, and it will compile and run just fine. But there will never be a case where obj is "partially initialized". Either it will be, or it won't be. Specifically, if this line throws an Exception:

obj = new SomeClass();

Then it is as if that line was never executed, as far as the value of obj is concerned. You initialize obj to null prior to that line, so if an exception is thrown then obj will still be null. In that case the program will not go into the if block at the end.

Or, if an exception is not thrown, then obj will no longer be null, and the code inside of the final if block will be executed.


It is perfectly possible; look closer: if the constructor throws an exception, obj will still be null.


If the SomeClass constructor throws an Exception obj will be NULL.


For me the object is null even after calling constructor:

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

Output:-

java.lang.Exception
hi
    at TestCls.<init>(TestCls.java:57)
    at TestCls.main(TestCls.java:48)

Conclusion: If the class constructor throws an Exception then the obj will be NULL.


The constructor could throw an Exception, just like any other call in Java could. For instance it may throw a NullPointerException if trying to call a method on a null reference. Consider the following example:

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

    }

}

As s is null in the Constructor a NullPointerException is thrown, so "Is Null" gets printed. There is no concept of a "partially constructed Object" - when you use new in Java it either works and you get the newly instantiated Object back or it doesn't work and you get the Exception.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜