加载类时调用

时间:2013-06-10 11:03:30

标签: java constructor

public class SuperClass{
    public SuperClass(){
        System.out.println("Super class");
    }
}

public class SubClass extends SuperClass{
    int i;
    {
        i=10;
    }
    public SubClass(){
        System.out.println("Subclass");
    }
    public static void main(String[] args){
        SubClass sc = new SubClass();
    }
}

我在所有可能的地方进行了调试,我看到第一次创建实例时,它首先进入SuperClass构造函数并打印Super Class,然后它才会到达实例变量,然后是初始化块,最后是SubClass构造函数和打印SubClass。

但是,我已经阅读了某个地方,在子类构造函数中,默认情况下调用了super(),这是它何时进入超类构造函数!!!

3 个答案:

答案 0 :(得分:9)

SubClass()构造函数隐式看起来像这样:

 public SubClass(){
    super();
    {
      i=10;
    }
    System.our.println("Subclass");
 }

根据JLS section 12.5

  

在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:

     
      
  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量。

  2.   
  3. 如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用此方法),则使用这五个相同步骤计算参数并以递归方式处理该构造函数调用。如果该构造函数调用突然完成,则此过程突然完成,原因相同;否则,继续步骤5.

  4.   
  5. 此构造函数不以同一类中另一个构造函数的显式构造函数调用开头(使用此方法)。如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super)。使用这五个相同的步骤评估参数并递归处理超类构造函数调用。如果该构造函数调用突然完成,则此过程突然完成,原因相同。否则,请继续执行步骤4.

  6.   
  7. 为此类执行实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中它们以文本方式出现在源代码中类。如果执行任何这些初始值设定项导致异常,则不会处理其他初始化程序,并且此过程会突然完成同样的异常。否则,请继续步骤5.

  8.   
  9. 执行此构造函数的其余部分。如果执行突然完成,则此过程突然完成,原因相同。否则,此过程正常完成。

  10.   

答案 1 :(得分:5)

嗯,那是因为你的SubClass构造函数实际上是这样的:

public SubClass() {
    super();
    {
       i=10;
    }
    System.out.println("Subclass");
}

如果你不打电话给super();明确地,编译器将为您隐式执行此操作。这意味着SuperClass构造函数被称为 first ,然后是`System.out.println(“Subclass”);

此外,super()必须是构造函数中的第一个语句。

您可以通过制作SuperClass 私有的构造函数(以及单独的文件中)来检查所有这些内容。编译器将在SubClass构造函数中向您显示错误,指出SuperClass中没有默认构造函数。

答案 2 :(得分:1)

构造函数始终调用super()。这是隐含的。

阅读documentation

  

如果构造函数没有显式调用超类构造函数,   Java编译器自动插入对无参数的调用   超类的构造函数。如果超级班没有   无参数构造函数,您将得到编译时错误。宾语   确实有这样的构造函数,所以如果Object是唯一的超类,   没问题。