2014-03-01 34 views
1

請看看這個片斷:在不同情況下,Java轉發引用的行爲是否有所不同?

public class A { 
    void method() { 
     System.out.print(B.j);//This is legal! 
     class C { 
      void method() { 
       System.out.print(j);//This is illegal! 
      } 
     } 
     final int j = 10; 
     class D { 
      void method() { 
       System.out.print(j);//This is legal! 
      } 
     } 
    } 
} 
class B { 
    static int j = 10; 
} 

我們可以訪問「BJ」在它的定義前的地方,而這是在C級訪問「最終詮釋J」的情況下,非法

java編譯器是否將本地類視爲簡單變量/對象?特別是,這種行爲的基本原理是什麼?我的意思是前進檢查工作的BJ,但它並沒有爲C類

+1

'System.out.print(j)'在D類內是合法的 – sanbhat

回答

0

設置你的代碼不能編譯拋開可能性內的「J」工作...

當A級是由classloader加載到內存中,B類也是如此,因爲它們在同一個文件中。所以當在運行時調用method時,B.j已經被分配在堆上。另一方面,當你在一個方法中聲明變量時,當你調用方法時,這些變量會按照你寫入的順序存儲在堆棧上,所以這裏的順序很重要。

+0

那麼你的意思是編譯器將類C和D看作變量? – mok

+0

聲明的順序在方法內很重要,但不在類內(除非它是構造函數,初始化塊等) – ktm5124

+0

請說明原因。肯定應該有一個原因。 – mok

5

我相信這是簡單的範圍界定。如果你用簡單的System.out.println()調用替換您的內部類,

public class A { 
    void method() { 
    System.out.print(j);//This is illegal! 
    final int j = 10; 
    System.out.print(j);//This is legal! 
    } 
} 

,你會發現你會得到同樣的消息。局部變量的作用域開始在那裏它們被申報並通過他們在聲明的塊的結尾繼續

要獲得關於參考到B的問題:考慮

public class A { 
    void method() { 
    System.out.print(k);//This is legal! 
    } 
    int k=17; 
} 

Java是不是單通編譯。類和它們的公開字段和方法可以被前向引用。故意做出的決定是局部變量不能被前向引用。我猜測這是爲了讓程序員建立受限範圍,而不必使用額外的塊語句級別 - 如果我引入了一個新變量,特別是初始化變量,我不希望任何人在此之前篡改它。

這就是Java局部變量如何發揮作用。這可能不是一個令人滿意的答案,但它是我們得到的最好的答案。

+0

當然你是對的顯然這是關於範圍的,但爲什麼我可以訪問Bj? – mok

+1

因爲Bj是靜態的,它不屬於任何單個對象或方法或執行路徑;它屬於B類。 – keshlam

+0

我剛剛將它定義爲靜態以避免生成對象,即使我再次刪除static關鍵字也是合法的(使用B類對象)。 – mok

相關問題