2012-07-05 17 views
35

爲什麼必須在構造函數完成之前初始化一個final變量?爲什麼必須在構造函數完成之前初始化最終變量?

public class Ex 
{ 
    final int q; 
} 

當我編譯這個代碼,我得到錯誤這樣

錯誤:變量q可能尚未初始化

+0

final關鍵字的一個屬性是它確保變量在初始化後不能更改狀態。它強制用戶在聲明時或在構造函數中進行初始化。 – 2012-07-05 13:14:09

+1

請參閱[this](http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4)。 – user1329572 2012-07-05 13:14:22

+3

「final」字段必須設置一次且僅設置一次。編譯器只能確定這是如果它在一個構造函數中設置的情況。 – 2012-07-05 13:15:00

回答

2

final改性劑可以防止您從量變到質變的變量值,因此你有在聲明它的地方初始化它。

14

由於final阻止您修改變量,但必須在某個時間點進行初始化,而構造函數是正確的。

就你而言,它將被稱爲blank final,因爲它在聲明時未被初始化。

0

Final modifier不允許使用change your variable value。因此,您需要在某處指定一個值,並且constructor是您必須在此情況下執行此操作的位置。

0

語言規範包含有關最終變量和字段屬性的特定保證,其中一個是正確構造的對象(即其構造函數成功完成的對象)必須具有對所有線程初始化並可見的所有最終實例字段。因此,編譯器會分析代碼路徑並要求您初始化這些字段。

11

變量值final只能設置一次。構造函數是類中代碼的唯一位置,您可以保證這將保持真實;構造函數只被調用過一次,但其他方法可以被調用多次。

6

應用於場的final關鍵字具有兩個效果之一:

    上的原始
  • ,它可以防止原始的值被改變(一個int不能改變值)
  • 上一個對象,它可以防止「變量的值」,即對對象的引用發生改變。也就是說,如果你有一個final HashMap<String,String> a,你只能設置它一次,你將不能再次執行this.a=new HashMap<String,String>();,但是沒有什麼能阻止你做this.a.put("a","b"),因爲那樣做不會修改引用,僅修改對象的內容。
9

A final變量必須在聲明或構造函數中初始化。

如果它在構造函數返回時尚未初始化,它可能永遠不會被初始化,並且可能仍然是未初始化的變量。編譯器不能證明它將被初始化,並因此引發錯誤。

Wikipedia excerpt解釋說得好:

最後一個變量只能初始化一次,或者通過一個初始化或賦值語句。它不需要在聲明點初始化:這被稱爲「空白最終」變量。一個類的空白final實例變量必須在聲明它的類的每個構造函數的末尾明確賦值;類似地,一個空白的最終靜態變量必須在聲明它的類的靜態初始化程序中明確賦值:否則,在兩種情況下都會發生編譯時錯誤。 (注:如果變量是一個參考,這意味着變量不能重新綁定引用另一個對象,但它引用的對象仍然是可變的,如果它最初是可變的。)

29

官方原因是,它是由定義Java Language Spefication 8.3.1.2

空白終審變量必須在聲明它的類的每一個構造年底被明確賦值;否則會發生編譯時錯誤。

一個空白final是一個最終變量,其聲明缺少一個初始化(即你所描述的)。

+0

默認構造函數應該初始化爲默認值?它適用於非最終變量,但爲什麼不適用於最終變量? – Sunil 2016-10-29 07:02:16

+2

這個答案只是重述了OP引用的行爲。它沒有說明行爲的原因,這是OP問的問題。 – ineedahero 2016-12-28 13:07:34

+0

@ineedahero我想我已經回答了op的問題:因爲語言是這樣定義的。爲什麼它被定義爲這樣的方式是誰寫的規範的問題,除非他或她在附近,我們只能做猜測工作...... – assylias 2016-12-28 13:09:02

相關問題