是否有与嵌套类关联的构造函数

时间:2012-04-13 05:52:45

标签: java constructor inner-classes

我想知道是否有任何构造函数涉及内部类。例如,考虑下面给出的代码片段

class MyOuter
{
   private int x= 10;

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

在另一个java文件中,我为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类一起使用时是否调用构造函数。如果是,那么是否有任何构造函数从内部类链接到外部类(如子类调用超类的构造函数等)。

5 个答案:

答案 0 :(得分:9)

扩展内部类时,可以观察内部类的构造函数链。

举个例子:

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的构造函数,并在.super对象实例上调用mainClass

现在您可以用这种方式创建NestedClassExtension实例:

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

因此主类必须存在,并且首先调用它的构造函数。然后是嵌套类的构造函数。

相反,如果您想在NestedClass之外创建一个MainClass实例,则需要编写:

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

另一次,必须先创建MainClass,然后再创建嵌套类。

答案 1 :(得分:3)

仅在有

时调用内部构造函数
MyOuter.MyInner mi = mo.new MyInner(); 

否则它甚至不会调用内部类构造函数,因为它没有实例化,就像执行静态块一样,但是在创建对象之前不会调用实例块和构造函数。

答案 2 :(得分:2)

如果未指定构造函数,则会创建一个不带参数的default constructor。如果你声明任何其他构造函数说MyInner(int i),那么默认的construtor的创建就会被忽略,你必须自己声明它(如果需要的话)。每个对象(没有任何例外)都是通过调用构造函数创建的。

答案 3 :(得分:2)

它们都使用默认的no-arg构造函数进行实例化。继承的super()中没有链接。只是你不能在没有实例化外部类的情况下实例化一个内部类。

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

答案 4 :(得分:1)

如果您编译建议的代码,然后在其上运行Java反编译器

javap MyOuter$MyInner

您将看到编译器如何实际声明内部类的构造函数:

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

在这里,您可以看到编译器通过声明一个包含对封闭类的引用的final字段成员来实现您的内部类。该字段被声明为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);
        }
   }
}

这里我用内部类链接构造函数。

同样,反编译器确保解释所有这些以确保外部实例作为参数传递给内部实例:

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