2017-05-05 53 views
2

當我初始化靜態內部類我期待的是外班也被初始化,將打印I should see this as well.然而這沒有發生,我只得到class Main作爲輸出Static Nested Class和未初始化外部類

class AA { 
    static { 
     System.out.println("I should see this as well."); 
    } 

    public static class BB { 
     BB() { 
      Object o = Main.class; 
      System.out.println(o.toString()); 
     } 
    }; 
} 

public class Test { 
    public static void main(String[] args) { 
     new AA.BB(); 
    } 
} 

有人能幫助我解釋這種行爲。

+0

靜態內部類與它們的外部類不像非靜態類很接近。事實上,您可以將外部類的靜態內部類看作某種名稱空間(或包)。 – Thomas

+3

*靜態嵌套類與其外部類(和其他類)的實例成員交互,就像任何其他頂級類一樣。實際上,爲了方便打包,靜態嵌套類在行爲上是嵌套在另一個頂級類中的頂級類。[source](http://docs.oracle.com/javase/tutorial/java/javaOO /nested.html) –

+0

編譯完成後,它們已經足夠分離,您可以在沒有其他類的情況下加載一個類。 – khelwood

回答

2

事情是:那靜態初始化塊被懶惰地執行。含義:這個代碼首次被執行時,AA類真的是「必需的」。但AA不需要實例化AA $ BB。

如果更改

BB() { 
    Object o = Main.class; 
    System.out.println(o.toString()); 
} 

真正要求AA類被加載:

BB() { 
    Object o = Main.class; 
    System.out.println(o.toString()); 
    new AA(); 
} 

然後其他字符串被打印了。請注意:它僅在您的代碼中BB是「內部」AA。從類加載器的角度來看,AA和BB是(不知何故)兩個獨立類來自兩個不同的類文件!

編輯,給出的問題「怎麼看」即:

A)我換成Main.class用的Test.class和編譯,我在文件系統中找到AA$BB.class AA.class Test.class之後。

B)現在你可以運行[javap][1] -c "AA$BB.class"看到更多有關這個類

+0

你說得對:」從類加載器的角度來看,AA和BB(不知何故)是來自兩個不同類文件的兩個獨立類!「---我想要檢查此行爲的任何工具或其他建議您查看此行爲的方式 –

+0

@Show Stopper,???您的問題包括顯示此行爲的代碼!這是您問題的基礎,它顯示了行爲! –

3

嵌套類創建一類獨特的內容。

在這裏,您將有兩類:

  • AA.class

  • AA $ BB.class

使用第二個不需要加載第一個作爲第二個是公共靜態類。

+0

沒有問題中的內部類。 –

+0

@盧布洛克? BB是AA的內部類。 – davidxxx

+0

'BB'是靜態的。因此,它不是內心階層。閱讀精細手冊http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3。 –