2012-04-13 107 views
3

我想知道是否有任何涉及內部類的構造函數。例如考慮下面是否有與嵌套類關聯的構造函數

class MyOuter 
{ 
    private int x= 10; 

    class MyInner 
    { 
     void dostuff(){ 
     System.out.println("The value of x is "+x); 
     } 
    } 
} 

給出。在另一個Java檔案i創建兩個MyOuter和MyInner類的實例代碼段如下所示

Class Program 
{ 
    public static void main(String [] args) 
    { 
     MyOuter mo = new MyOuter(); 
     MyOuter.MyInner mi = mo.new MyInner(); 
     mi.dostuff(); 
    } 
} 

上面代碼段編譯罰款和給出的輸出「的x的值是10「。

我在這裏想知道的是當new()與MyInner類和MyOuter類一起使用時是否調用構造函數。如果是,那麼是否有從內部類到外部類的任何構造函數鏈接(如超類的子類調用構造函數等)。

回答

8

當擴展內部類可以觀察到的內部類的構造函數鏈。

拿這個例子:

public class MainClass { 

    public MainClass(String value) { 
     System.out.println("mainValue: " + value); 
    } 

    public class NestedClass { 

     public NestedClass(String nestedValue) { 
      System.out.println("nestedValue: " + nestedValue); 
     } 
    } 

} 

然後再擴展NestedClass這樣

public class NestedClassExtension extends NestedClass { 

    public NestedClassExtension(MainClass mainClass, String nestedValue) { 
     mainClass.super(nestedValue); 
    } 
} 

所以你可以看到,你可以到你的嵌套類傳球的超級構造函數調用該構造函數MainClass,並在mainClass上調用.super對象實例。

現在你可以通過這種方式創建NestedClassExtension實例:

NestedClassExtension extension = new NestedClassExtension(new MainClass("main"), "nested"); 

所以主類必須存在,它的構造是首先被調用。然後是嵌套類的構造函數。

相反,如果你想外面創建NestedClass實例MainClass你必須寫:

MainClass mc = new MainClass("main"); 
mc.new NestedClass("nested"); 

還有一次,在MainClass必須首先創建,然後是嵌套類。

3

內部構造函數只調用時,你有

MyOuter.MyInner mi = mo.new MyInner(); 

否則它甚至不會調用內部類的構造函數,因爲它不會被實例化,像靜態塊被執行,但實例塊和構造不調用,直到你創建一個對象。

2

如果您未指定構造函數,則會創建一個不帶參數的default constructor。如果您聲明任何其他構造函數說MyInner(int i)默認construtor的創建ommited,您將不得不自己聲明(如果需要)。每個對象(沒有任何例外)都是通過調用一個構造函數來創建的。

1

如果您編譯您建議的代碼,然後在其上運行了Java反編譯

javap MyOuter$MyInner 

你會看到怎樣的編譯器實際上聲明構造你的內部類:

public class MyOuter$MyInner extends java.lang.Object{ 
    final MyOuter this$0; 
    public MyOuter$MyInner(MyOuter); 
    void dostuff(); 
} 

在這裏,您可以請參閱編譯器通過聲明一個持有對封閉類的引用的最終字段成員來實現您的內部類。該字段被聲明爲final,因此需要提供一個值來實例化Inner類。

當你做MyOuter.MyInner mi = mo.new MyInner()編譯器確保封裝實例作爲參數傳遞。

這是由編譯器自動完成的,因此您不能將創建內部類與創建外部類鏈接起來,因爲外部實例在創建內部類時必須已經存在。

儘管如此,您可以在內部類的其他聲明構造函數之間進行構造函數鏈接。

例如,如果像這樣的代碼:

public class MyOuter 
{ 
    private int x= 10; 

    public class MyInner 
    { 
     private int y = 0; 

     public MyInner(){ 
      this(10); 
     } 

     public MyInner(int value){ 
      this.y = value; 
     } 

     void doStuff(){ 
      System.out.println("The value of x is "+x); 
     } 
    } 
} 

在這裏,我鏈接構造withing內部類。

同樣,反編譯,確保來解釋這一切,以確保外實例作爲參數傳遞給內部一個通過:

public class MyOuter$MyInner extends java.lang.Object{ 
    final MyOuter this$0; 
    public MyOuter$MyInner(MyOuter); 
    public MyOuter$MyInner(MyOuter, int); 
    void doStuff(); 
}