2011-05-06 89 views
2

我聽說,有可能寫這樣一些代碼這個當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)); 
    } 

} 
+0

你能發佈一個鏈接到可疑信息的來源嗎? – 2011-05-06 10:12:57

+0

@Laurent:mat be this:http://stackoverflow.com/questions/5909818/java-exception-thrown-in-constructor-can-my-object-still-be-created – 2011-05-06 10:14:29

回答

2

首先聲明並初始化一個變量。

SomeClass obj = null; 

在下面的行你(1)創建一個新實例,(2)存儲參考。

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

現在我們假設,實例化(步驟1)失敗並拋出異常:JVM將繼續在處理該異常的下一個catch塊。所以第2步不會執行,變量將保持其實際狀態。

現在是可能實例已被部分初始化。老實說,我不知道,那是JVM的內部。但是因爲沒有任何東西可以引用這個部分初始化的實例,它將在下一次出現。

+0

+1有人會認爲部分初始化實例在內存中一直存在,直到它獲得GC'd,因爲構造函數只是在實例化後初始化對象的特殊方法。看起來好像JVM需要額外的工作來取消這種行爲。 – 2011-09-02 18:04:12

2

這是完全可能的。

我不確定我是否理解你的問題,儘管你已經自己回答了:if構造函數拋出異常,obj可能爲null。

1

這是完全可能的;仔細觀察:如果構造函數拋出異常,obj仍然是null

1

如果SomeClass構造函數拋出異常obj將爲NULL。

2

你當然可以編寫這樣的代碼,它會編譯並運行得很好。但是永遠不會存在obj被「部分初始化」的情況。要麼它會,要麼就不會。特別是,如果這條線拋出Exception

obj = new SomeClass(); 

然後就好像從來沒有執行這一行,就爲obj價值而言。您在該行之前將obj初始化爲null,因此如果拋出異常,則obj仍將爲null。在這種情況下,程序最後不會進入if塊。

或者,如果不拋出異常,則obj將不再爲null,並且最終的if塊內的代碼將被執行。

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

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是在構造一個NullPointerException被拋出空,所以 「IS NULL」 被打印出來。沒有「部分構造的對象」的概念 - 當你在Java中使用new時,它可以工作,並且你得到新實例化的Object,或者它不起作用,你會得到Exception。

相關問題