2013-01-21 42 views
3

通過JLS 8.3.2.3時,我無法理解下面的代碼。Java靜態初始化塊上的奇怪代碼

class Z { 
static { i = j + 2; } 
static int i, j; 
static { j = 4; } 
} 

的代碼導致錯誤Cannot reference a field before it is defined

但如果我更改代碼以

class Z { 
static { i = 2; } 
static int i, j; 
static { j = 4; } 
} 

的代碼編譯得到。但是在這兩種情況下,變量定義都在初始化塊之後。這背後的奧祕是什麼?

+1

它們是聲明,在任何代碼運行之前就已知...這就像問我爲什麼可以調用方法上面定義的方法來調用方法 – Esailija

+1

@Esailija:'i'和'j'之間有什麼區別。爲什麼只爲'j'錯誤?如果您提供更多信息將會很好。 – xyz

回答

8

您可以賦值爲比其聲明更早的值 - 您只是不能它。因此,這也會失敗:

static { System.out.println(j + 2); } 
static int j; 

雖然這是好的:

static { j = 5; } 
static int j; 

一個在section 8.3.2.3四個條件的,無效的用法是:

  • 的使用是不是在左邊一個任務的手邊。

(這一節的雙底片正在我的頭很疼,但我認爲有關!)

說實話,來規範的這些部分是我以前做的最差的一個看 - 這是真的不清楚。但結果是,你可以分配但不能讀:) :)

+1

你的意思是 - 「你只是*不能*讀它」,在你的第一個陳述中。 –

+0

@RohitJain:是的,謝謝。 –

0

i = j + 2;你使用變量j初始化在不同的靜態塊。

您應該將所有東西都放在只有一個靜態塊中,j初始化和表達式中以獲得代碼編譯。此代碼的工作:

public class Z { 

    static int i, j; 
    static { j = 4; 
      i = j + 2; } 

} 

達維德

1

事實上,它的一個基本的編譯器,

語句是向左向右執行的任務。

例如i=2;

這意味着2分配給i和2是恆定的,因此沒有必要將它聲明

在另一方面,如果我們寫

i=j+2; 

它將首先編譯j和然後將其指定到我因此它會導致錯誤,因爲j尚未定義。