2010-11-04 62 views
12

在很多示例代碼片段中,我看到的變量是用空值賦值的,後來分配了更有意義的值。爲什麼實例化具有空值的變量

我只是想知道爲什麼人們可以這樣做。我猜try-catch塊可能會進入這個,但我也看到變量實例化將在try塊內的空值。

(我敢肯定,這是一個相當語言無關的問題,但只是參考我在Java程序幾乎完全)

所有的見解表示讚賞!

+3

我認爲這是一個有效的問題。 +1來平衡downvote。 – 2010-11-04 18:05:19

+0

這就是downvoter不發表評論時發生的情況。 – 2010-11-04 18:06:10

+0

僅僅因爲在很多情況下,代碼根本無法編譯。現在爲什麼Java規範要求這是另一個問題,但是指出了確切的編譯器錯誤消息的MForster +1。請注意,您甚至不需要編譯有效的* .java *文件來獲取此錯誤消息。例如:IntelliJ IDEA(令人驚歎的Java IDE)即使在部分AST上也會實時警告你**錯誤**(即:部分.java文件,因爲它不完整)。 – SyntaxT3rr0r 2010-11-04 18:42:52

回答

13

在某些情況下,Java編譯器會檢測變量是否未在所有可能的控制流中初始化並輸出錯誤。爲了避免這些錯誤信息,有必要明確地初始化變量。

例如,在這種情況下:

public Integer foo() { 
    Integer result; 

    if (Math.random() < 0.5) { 
     result = 1; 
    } 

    return result; 
    } 

,編譯器將給出該錯誤消息:「局部變量結果可能沒有被初始化」。

這裏是什麼Java Language Specification說:

每一個局部變量(§14.4)和每一個空白的最終(§4.5.4) 場(§8.3.1.2)必須有一個明確指定值時 其價值的任何訪問發生。 Java編譯器必須攜帶 進行特定的保守流分析,以確保在本地變量或空白最終字段f的每個訪問中都有 f在訪問之前明確分配;否則必須發生編譯時錯誤 。

請注意(與字段!)局部變量不會自動初始化爲null

+0

它發出錯誤以幫助您避免運行時異常!我不會說這是必要的。事實上,我認爲不確定每個控制流是否有一個有效的對象是非常糟糕的。 – wheaties 2010-11-04 17:59:48

+0

我指的是編譯器的錯誤信息。我認爲這些都是由語言規範來規定的。 – MForster 2010-11-04 18:01:19

+12

是否有人認爲QuakerOat問這個問題很奇怪,Wheaties評論了一個答案? – 2010-11-04 18:01:43

4

個人而言,我不喜歡它的成員字段,將在構造函數中的值。曾經有一段時間,我認爲這是明確的,但實際上在將字段明確指定爲null或採用默認值的字段之間存在字節碼差異。

即使對於那些開始時爲空(然後初始化後的某個時間得到的值)我不是他們的大風扇領域。它通常只是強調了開發者的誤解。

在try-catch相關性是在這樣的情況下:

Reader r = null; 
try { 
    r = ...; 
    //do something that could throw an exception 
} finally { 
    if (r != null) { //wouldn't compile without assignment to null 
     r.close(); 
    } 
} 

因爲r是一個局部變量這裏需要的值,然後才能使用它,這樣的分配是必要的。如果賦值爲null發生在與後續重新分配和/或使用相同的代碼路徑中,那麼這可能只是誤導性的冗餘。

+0

我通常只使用不可變對象生成代碼,因此在構造函數中接受值的成員字段通常在我的代碼中都標記爲* final *,這使得這個觀點有點沒有意義:在這種情況下,您根本不能將它分配* null *先在CTOR中改變它。 – SyntaxT3rr0r 2010-11-04 18:45:40

+0

@ Webinator:當然。最終成員的一個不錯的副作用。 – 2010-11-04 19:00:55

0

是的,多次想過這個問題。

現在,我通常給一個對象一個初始值null,以及用於簡單類型值毫無意義。原因,有時你不能確定JRE給變量賦予初始值。有時你需要判斷這個變量是否爲空,也許你忘記了init。一些錯誤很容易找到,如果給變量一個初始值。