2012-04-13 76 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(); 
}