在很多示例代碼片段中,我看到的變量是用空值賦值的,後來分配了更有意義的值。爲什麼實例化具有空值的變量
我只是想知道爲什麼人們可以這樣做。我猜try-catch塊可能會進入這個,但我也看到變量實例化將在try塊內的空值。
(我敢肯定,這是一個相當語言無關的問題,但只是參考我在Java程序幾乎完全)
所有的見解表示讚賞!
在很多示例代碼片段中,我看到的變量是用空值賦值的,後來分配了更有意義的值。爲什麼實例化具有空值的變量
我只是想知道爲什麼人們可以這樣做。我猜try-catch塊可能會進入這個,但我也看到變量實例化將在try塊內的空值。
(我敢肯定,這是一個相當語言無關的問題,但只是參考我在Java程序幾乎完全)
所有的見解表示讚賞!
在某些情況下,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
。
個人而言,我不喜歡它的成員字段,將在構造函數中的值。曾經有一段時間,我認爲這是明確的,但實際上在將字段明確指定爲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發生在與後續重新分配和/或使用相同的代碼路徑中,那麼這可能只是誤導性的冗餘。
我通常只使用不可變對象生成代碼,因此在構造函數中接受值的成員字段通常在我的代碼中都標記爲* final *,這使得這個觀點有點沒有意義:在這種情況下,您根本不能將它分配* null *先在CTOR中改變它。 – SyntaxT3rr0r 2010-11-04 18:45:40
@ Webinator:當然。最終成員的一個不錯的副作用。 – 2010-11-04 19:00:55
是的,多次想過這個問題。
現在,我通常給一個對象一個初始值null
,以及用於簡單類型值毫無意義。原因,有時你不能確定JRE給變量賦予初始值。有時你需要判斷這個變量是否爲空,也許你忘記了init。一些錯誤很容易找到,如果給變量一個初始值。
我認爲這是一個有效的問題。 +1來平衡downvote。 – 2010-11-04 18:05:19
這就是downvoter不發表評論時發生的情況。 – 2010-11-04 18:06:10
僅僅因爲在很多情況下,代碼根本無法編譯。現在爲什麼Java規範要求這是另一個問題,但是指出了確切的編譯器錯誤消息的MForster +1。請注意,您甚至不需要編譯有效的* .java *文件來獲取此錯誤消息。例如:IntelliJ IDEA(令人驚歎的Java IDE)即使在部分AST上也會實時警告你**錯誤**(即:部分.java文件,因爲它不完整)。 – SyntaxT3rr0r 2010-11-04 18:42:52