2012-07-23 34 views
2

Java不允許你使用可能還沒有一個方法範圍內初始化的變量。類範圍內的未初始化變量仍然可以由類方法返回,並且該值默認爲null。爲什麼使用未初始化的變量時,java的治療類範圍和方法範圍不同?

爲什麼不同的處理兩個不同的範圍呢?

public class TestClass { 

    Integer i; 
    Double d; 

    public TestClass() { 
     d = 1d; 
    } 

    public Double getD() { 
     return d; 
    } 

    public Integer getI() { 
     return i; 
    } 

// public Integer getSomeInt() { 
//  Integer i; 
//  return i; 
// } 

    public static void main(String[] args) { 
     TestClass myClass = new TestClass(); 
     System.out.println(myClass.getI().getClass()); 
    } 
} 

這導致一個NullPointerException,但在返回內getSomeInt i()是一個編譯器錯誤,因爲「變量可能沒有被初始化」。

回答

3

背後的原因是Java靜態代碼分析的侷限性。編譯器能夠毫無疑問地證明,在初始化之前,您不會讀取堆棧分配的本地var。對於堆分配的內存來說這是不可能的,因此Java要求在將指針暴露給它之前將所有堆分配的存儲設置爲零。

該規則的結果是,所有堆分配的默認值都爲零(false,null,無論二進制零對於該類型而言)。

+0

謝謝,這是我正在尋找的答案。爲什麼堆分配資源不可能檢查它們是否已初始化? – user831885 2012-07-23 13:31:02

+0

因爲它們可以很容易地發佈到外星代碼甚至其他線程。這使得理論上不可能在第一次讀取之前確保初始化。 – 2012-07-23 13:32:05

2

因爲成員變量的默認值(如果未初始化)等等Inull,如果你對空調用方法會導致對NullPointerException

和局部變量,它們必須被初始化之前以其他方式使用它會變成編譯時錯誤

局部變量是略有不同;編譯器從不將默認值分配給未初始化的局部變量。如果你不能初始化在聲明局部變量,請確保您嘗試使用它之前,它分配一個值。訪問未初始化的本地變量將導致編譯時錯誤。 [....]

+0

如果它是一種基本的數據類型,並且它是好的,但是如果它是一個對象哦,它在被訪問時會拋出NullPointerException,並且它看起來不太好,至少約束可能已經存在於非原始類成員 – Jayy 2012-07-23 12:21:37

+0

使用構造函數初始化默認值 – 2012-07-23 12:29:18

1

這真的很簡單。成員變量會自動初始化爲默認值,而局部變量則不會。

當你

public Integer getSomeInt() { 
    Integer i; 
    return i; 
} 

隱藏this.ireturn i你指的是(初始化)當地變量。


那麼爲什麼的成員變量初始化時自動局部變量都沒有?

歸根結底,這是隻有語言的設計者可以回答的問題,但如果要我猜我會說這是由於其零出被分配所有內存的性能問題。當涉及到對象時,強制程序員顯式初始化所有字段會是一種痛苦。


從JLS(變量4.12.3種):

當製備它的類或接口(§12.3.2)和 被初始化爲缺省,創建一類可變值(§4.12.5)。

[...]

局部變量聲明聲明可以含有 初始化變量的表達式。與初始化表達式中的局部變量然而 未初始化,直到 聲明它執行局部變量的聲明語句。(它已 被初始化之前被使用明確賦值(第16章,正定 分配)防止從本地變量的值的規則或以其他方式分配一個值。)

+0

+1,但我認爲OP在質疑多一點。他指出了方法和類變量的不同行爲。所以解釋了爲什麼方法變量默認沒有被初始化,但是類成員會幫助我想。 – 2012-07-23 12:19:12

0

所有字段被設置在隱式初始化構造函數在super之後但在其他之前。對象引用設置爲null,原始值設置爲0,false等。 此隱式初始化不在方法中完成。

+0

此外,編譯器可以通過檢查代碼流來判斷局部變量是否已初始化。對於一個成員變量來說,它比較困難,而且意味着仔細閱讀所有不同的方法調用。但是,不能保證任何這些方法都被調用。編譯器幾乎忽略了這一點,雖然像eclipse這樣的工具可以很好地告訴你什麼時候一個變量從來沒有被讀過或寫過它聲明的類中。 – Matt 2012-07-23 12:27:39