2010-06-08 28 views
1

我有以下代碼:這個結果在Java中的解釋是什麼?

public class Main { 
    private int i = j; //1 
    private int j = 10; 

    public static void main(String[] args) { 
     System.out.println((new Main()).i);  
    } 
} 

並且在第1行,因爲非法 前方參照編譯錯誤。
但是,當我嘗試下面的代碼:

public class Main { 
    int i = getJ(); //1 

    int getJ(){ 
     return j; 
    } 
    int j=10; 
    public static void main(String[] args) { 
     System.out.println(new Main().i); 
    } 
} 

它工作正常,結果爲0。
爲什麼會出現在1號線沒有違法 向前參考這裏。這兩個代碼類似於我。

回答

6

方法可以在聲明之前使用。

private int j = 10;是必須在某個時間點執行的可執行語句。因此,字段聲明的排序是有意義的。

方法聲明本身不可執行。
因此,方法的排序是完全沒有意義的。

+0

「return j」呢? j在聲明之前使用 – 2010-06-08 21:38:21

+2

'return j;'在方法爲_called_時執行,而不是在_defined_時執行。將該方法移到其他地方不會有任何區別。 – SLaks 2010-06-08 21:39:03

2

因爲在實例初始化完成之前,您正在顯式調用方法並訪問成員變量。編譯器能夠阻止你做出愚蠢的事情是有限制的! :-)

0

J在被引用進行賦值之前未被聲明

4

該規則僅適用於字段。具體而言(JLS 8.3.2.3):

一個成員的聲明需要 出現文本地使用 之前它僅當構件是一個實例 類 或接口C和所有的(分別爲靜態)字段所述 下列條件成立:

  • 在一個實例(分別靜態)可變 初始化的C或在一個實例(分別靜態)初始化時的使用C.
  • 該用法不在作業的左側。
  • 用法是通過一個簡單的名字。
  • C是封閉使用的最內層的類或接口。

所有的條件都適用於第一個例子。

  1. j是一個實例字段。
  2. 我是一個實例字段。
  3. j用於右側。
  4. j是一個簡單的名字(基本上,該字段是直接使用的)
  5. 主要是兩者都包含的最內層類。

至少有一個(「用法是通過簡單名稱」)不適用於第二個示例。基本上,編譯器試圖趕上圓形這樣的錯誤:

int i = j + 1; 
int j = i + 1; 

這有點過於謹慎,但大多工作。在執行j = 10之前,j仍然是0,所以這就是我設置的值。無法擴展您的getJ示例來創建循環(當然,還有其他方法可以在運行時創建無限遞歸)。

2

Java運行時信息中包含一個實例變量,即int,稱爲「j」 但是,直到字節碼解釋器達到初始化,該值纔會被設置爲10。

這就是您將默認int值視爲返回值的原因。

相關問題