2012-04-13 8 views
3

内部クラスに関連するコンストラクタがあるかどうかを知りたい。例えば上記のコードは罰金コンパイルして「の出力を与える 入れ子クラスに関連付けられたコンストラクタがあるか

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

以下のように私はMyOuterとMyInner両方のクラスのインスタンスを作成して、別のjavaファイルで

class MyOuter 
{ 
    private int x= 10; 

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

下記のコードスニペットを考えますxの値は10 "です。

ここで知りたいのは、MyInnerクラスとMyOuterクラスでnew()を使用したときにコンストラクタが呼び出されるかどうかです。はいの場合は、内部クラスから外部クラスにチェーンするコンストラクタがあります(たとえば、スーパークラスのコンストラクタを呼び出すサブクラスなど)。

答えて

8

あなたは内部クラスを拡張するときは、内部クラスのコンストラクタチェーンを観察することができます。そう、あなたがそのコンストラクタにあなたのネストされたクラスの通過のスーパーコンストラクタを呼び出すことができることを見ることができます。この

public class NestedClassExtension extends NestedClass { 

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

ようNestedClassを拡張し、その後

public class MainClass { 

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

    public class NestedClass { 

     public NestedClass(String nestedValue) { 
      System.out.println("nestedValue: " + 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)と言う場合、デフォルトコンストラクタの作成は省略され、必要に応じて自分で宣言しなければなりません。すべてのオブジェクト(例外なし)は、コンストラクタを呼び出すことによって作成されます。

2

これらは両方とも、デフォルトの引数なしのコンストラクタを使用してインスタンス化されます。継承のsuper()のような連鎖はありません。インスタンス化せずに内部クラスをインスタンス化することはできません。

Read the difference between static and non-static inner class.

1

あなたは

javap MyOuter$MyInner 

をあなたの提案コードをコンパイルし、それでJavaの逆コンパイラを実行する場合は、コンパイラが実際にあなたの内部クラスのコンストラクタを宣言する方法を確認します:

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コンストラクタを連鎖しています。

ここでも、逆コンパイラは、外側のインスタンスは、内側1にパラメータとして渡されることを確認するために、このすべてを解釈するために確保さ:

public class MyOuter$MyInner extends java.lang.Object{ 
    final MyOuter this$0; 
    public MyOuter$MyInner(MyOuter); 
    public MyOuter$MyInner(MyOuter, int); 
    void doStuff(); 
} 
関連する問題