2015-07-19 41 views
0

爲什麼以下編譯爲什麼不能在下一行分配?

class Foo { 
    Object x; 
    String s = (String) x; 
} 

及以下不編譯?

class Foo { 
    Object x; 
    String s; 
    s = (String) x; 
} 

我是否缺少一些JLS規則?我知道這一定很愚蠢,但我仍然需要知道背後的原因。

+0

您不能在方法外寫入分配。將's =(String)x'放在構造函數中,它將被編譯。 – Turing85

+0

好像你不能在塊之外沒有類型的變量賦值。 –

+0

爲什麼java的力量做到這一點?任何安全原因?一個例子會很好 –

回答

2

non-static塊(此處標記爲{ })有權訪問variables,和methods。在執行constructor期間,在調用super class constructor之後調用此塊。

因此,可以在這個塊中進行初始化。

您可以將initialize實例變量與聲明一起放入一行或non-static block的內部。

然後,initialization一旦調用constructor就會發生。 (因爲它在塊中執行代碼)。

因此,該塊實際上是constructor執行的一部分。

另一方面,如果你將自己的初始化代碼寫入類本身,它沒有任何意義,因爲沒有方法執行該行,因此是不正確的。

所以,方法1:初始化隨着宣言:

class Foo { 
    Object x; 
    String s = (String) x; 
} 

或者,方法2:初始化塊,聲明之後:

class Foo { 
    Object x; 
    String s; 
    { 
     s = (String) x; 
    } 
} 

記住,這種非靜態在調用超類構造函數之後,在構造函數執行過程中調用該塊。

+0

Thanks.Your答案增加了我的初學者的知識。 –

+0

@ShubhamKharde [請不要對您的問題或回答說「謝謝」](http://stackoverflow.com/help/someone-answers)。 – Turing85

2

你可以使用一個實例級別塊,如果他們不在聲明語句的一部分

{ 
    s = (String) x; 
} 

賦值語句應該屬於一個塊。 甲可以是任何東西(一個方法,構造等)

+0

謝謝。我想我背後的原因是爲了確保封裝?不是嗎?通過這樣做,我們只在方法或塊內修改字段。 –

+0

編號不封裝..它只是如何設計語言結構。 – TheLostMind

2

通常,類聲明只能包含類體聲明。它們是:

  • 域聲明
  • 方法聲明
  • 類聲明(你的類中定義的類)
  • 接口聲明
  • 實例初始化
  • 靜態初始化
  • 構造函數聲明。

s = (String) x; 

是無那些。

您可以按照@TheLostMind的建議使用初始化程序聲明,或按照@ Turing85的建議將賦值放入構造函數中。你也可以把這樣的一行放入其他方法中。你甚至可以做這樣荒謬的事情:

class Foo { 
Object x; 
String s; 
String s2 = s = (String) x; 
} 

聲明x,s和s2的行都是字段聲明。在s2行的第一個「=」之後的奇怪東西是s2的所有初始化器。而賦值表達式s = (String) x是一個返回String的合法表達式,因此它適合於此。

但是沒有經過修改的s = (String) x;是一個語句,而不是一個類體聲明,所以它不能按照Java規則(a.k.a.Java Language Specification)去那裏。

相關問題