2016-02-11 89 views
5

這裏是一些示例代碼(假設Java 8)。這個「s」有效嗎?

while (true){ 
    Socket s = serverSocket.accept(); 
    // some code here ... we don't assign anything to s again here ... 
} 

s有效最終在循環內嗎?

+0

我不這樣做。假設我不這麼做,我會問「有效的最終」。 –

+2

@ cricket_007:如果你從來沒有這樣做過,那麼's'仍然是有效的。 – Makoto

+0

@ peter.petrov:它讓我感到有些痛苦,但是這個重複可以回答你的問題。在Java 8中,這是有效的;在Java 7和更高版本中,這是非常複雜的。 – Makoto

回答

5

假設s沒有分配過去的聲明,那麼,s是「有效的最後」,根據JLS, Section 4.12.4,它定義它,你的情況:未申報

某些變量最終被代替考慮有效最終

  • 的局部變量,其說明符具有一個初始化(§14.4.2)是有效最終如果以下全部屬實:

    • 未聲明final

    • 它永遠不會出現在賦值表達式(§15.26)中的左側。 (請注意,包含初始化局部變量聲明符是賦值表達式。)

    • 它永遠不會發生作爲前綴或後綴增量或減量操作者(§15.14,§15.15)的操作數。

  • 一個局部變量,其聲明符缺少初始化實際上最終如果以下所有條件都爲真:

    • 它不聲明爲final。

    • 每當它出現在賦值表達式中的左手邊時,它肯定是未分配的,並且在賦值之前沒有明確賦值;也就是說,它肯定是未賦值的,並且在賦值表達式(§16(定義賦值))的右側之後沒有明確賦值。

    • 它永遠不會發生作爲前綴或後綴增量或減量運算符的操作數。

你只在聲明時分配s,並作爲一個對象時,它不能是遞增或遞減的運算數,所以它是有效的決賽。

它還聲明變量在另一種情況下可以是有效的最終結果,如果它在聲明時沒有被賦值,只要它只被賦值一次,它肯定不會在聲明前被賦值,並且在聲明後明確賦值。

此外,在該節結束時,它指出:

如果一個變量是有效final,加上final修飾符其聲明將不會引入任何編譯時錯誤。相反,如果刪除了final修飾符,則在有效程序中聲明爲final的局部變量或參數將有效。

您應該能夠明確地將其設置爲final而不會導致編譯器錯誤。如果是這樣,那實際上是最終的。

+0

嗯。你引用的兩個部分似乎對於像'int i'這樣的情況不一致。我= 3;'。前者似乎認爲'i' *不是*有效的最終結果(因爲它的聲明者沒有一個初始化器,它確實發生在賦值語句的左側),而後者似乎是說'i' * *實際上是最終的(因爲'final int i; i = 3;'完全有效)。規範中的其他內容是否可以解決這種明顯的差異? – ruakh

+0

爲簡潔起見,我已經將其他方式的引用留下來,在分割聲明/單個賦值的情況下,它可以成爲有效的最終結果。我會包括它...... – rgettman

+0

啊,我明白了;謝謝。我認爲你更喜歡簡潔是對的。也許只是把第二個要點留作「一個局部變量,其聲明符缺少一個初始化符,如果[...]」實際上是最終的,也就是說,用「[...]」替換單詞「if」後面的所有內容? (順便說一句,哦,還有+1。) – ruakh