在非静态块之前调用构造函数?

时间:2014-05-29 13:06:08

标签: java static default-constructor

这是我的计划:

public class Num2 {

   static
   {
        System.out.println("static block -1");
   }
   int no;
   Num2(int n)
   {
       no=n;
       System.out.println("Num");
   }
   Num2()
   {
        no=0;
        System.out.println("default num");
   }
   {
        System.out.println("Non-static block of num1");
   }
}



class call_by_value2 extends Num2
{
       static
       {
           System.out.println("static block of call by value");
       }  
       {
           System.out.println("non- static block of call by value");
       }
       call_by_value2()
       {   
          System.out.println("Default of call by value");
       }
       static void changeno(Num2 n1,Num2 n2)
       {
          Num2 n=new Num2();
          n=n1;
          n1=n2;
          n2=n;
       }
       public static void main(String[] args)
       {
          System.out.println("Main method");
          call_by_value2 c=new call_by_value2();
       }
 }

输出为:

static block -1
static block of call by value
Main method
Non-static block of num1
default num
non- static block of call by value
Default of call by value

这是期望的输出,因为我们知道首先调用非静态块然后构造函数。但是当我修改这个程序并运行它时:

public class Num2 {

   static
   {
       System.out.println("static block -1");
   }
   int no;
   Num2(int n)
   {
       no=n;
       System.out.println("Num");
   }
   Num2()
   {
       no=0;
       System.out.println("default num");
   }
   {
       System.out.println("Non-static block of num1");
   }
}



class call_by_value2 extends Num2
{
      static
      {
          System.out.println("static block of call by value");
      }  
      {
          System.out.println("non- static block of call by value");
      }
      call_by_value2()
      {   
          super(50);
          System.out.println("Default of call by value");
      }
      static void changeno(Num2 n1,Num2 n2)
      {
          Num2 n=new Num2();
          n=n1;
          n1=n2;
          n2=n;
      }
      public static void main(String[] args)
      {
          System.out.println("Main method");
          call_by_value2 c=new call_by_value2();
      }
}

现在输出为:

static block -1
static block of call by value
Main method
Non-static block of num1
Num
non- static block of call by value
Default of call by value

所以我的问题是,如果包含super()方法的callbyvalue2 class的默认构造函数最后运行Num2类的参数化构造函数如何在callbyvalue2类的默认构造函数的输出之前给出输出?

1 个答案:

答案 0 :(得分:3)

不,这是你拨打电话时会发生的事情。

new Num2() ;

1)所有变量都使用默认值(0,null,false,' \ u0000')初始化,包括从超类继承的那些。

2)调用隐式或显式超类构造函数,直到Object类(不允许传递任何局部变量或方法作为参数返回到超类构造函数调用)。请注意,此时虽然调用了隐式或显式构造函数,但它们不会在其中执行任何代码。

(如果你有一个空构造函数,编译器将对no-args超类构造函数进行隐式调用,因此它不会在方法内部执行任何操作,直到达到最顶层的超类构造函数,因为每个构造函数中的第一行代码都是super();无论你是否使用它。如果超类没有no-args构造函数可用,那么你必须显式提供一个作为你的子类构造函数中的第一行代码,例如super ("字符串参数");)

3)当达到顶级超类构造函数时,在该级别声明的变量将分配其初始化(显式赋值,例如int i = 23;),块语句在构造函数之前执行,无论它们在类中声明的位置和构造函数在所有非静态块执行后执行。

然后,点3将继续执行继承树,直到Num2()

示例1第一个示例将无法编译。

class Animal{
    Animal(int){

    }
}

class Dog extends Animal
{
    Dog(){
        // right here compiler will place an implicit call to super() ; not seen, at compile time.
        // since there is no no-args constructor available in class Animal compiler will issue a warning and stop compiling. Remember that a no-args constructor is provided by default ONLY if no other constructor was provided by the programmer. In this example we have a constructor in our superclass that takes an int as argument and so we must explicitly tell the compiler to call super(24);
    }
}

示例2

class Animal{

}

class Mammal extends Animal{
    Mammal(int x){ 

    }
}

class Dog extends Mammal{
    Dog(){
        super(24) ;
    }

    Dog(int x){
       super(x) ;
    }
}

class BullDog extends Dog{
    BullDog(){
        this(24) ;
    }

    BullDog(int x){
        super(x) ;
    }
}

现在,如果我们要使用no-args构造函数创建BullDog实例,则会发生以下构造函数调用。

1 BullDog();

2 BullDog(24);

3只狗(24);

4哺乳动物(24);

5这里虽然似乎没有任何东西记住编译器提供对超级构造函数的隐式调用,所以这里将是一个调用,如Anima();

6这里的类Animal似乎没有任何构造函数,但是编译器将提供以下no-args构造函数,其中默认调用super,它应该是Object类的no-args构造函数。

Animal(){
    super() ;
}

所以6就像Object();

您现在应该理解为什么在到达Object构造函数之前,任何构造函数中的代码都不会执行,这是因为总是会调用超类构造函数作为第一行。如果省略它,最好在你的seperclass中使用no-args构造函数,这样它就可以使用编译器默认提供的内容,否则你必须明确地声明它。