Java中父类构造器的隐式调用和显式调用

Java 1696℃

当创建任何 Java 对象时,程序总会先依次调用每个父类非静态初始化块、父类构造器(总是从 Object 开始,因为Java 程序里所有类的最终父类都是 java.lang.Object 类)执行初始化,最后才调用本类的非静态初始化块、构造器执行初始化。

当调用某个类的构造器来创建Java 对象时,系统总会先调用父类的非静态初始化块进行初始化。这个调用是隐式执行的,而且父类的静态初始化块总是会被执行。接着会调用父类的一个或多个构造器执行初始化,这个调用既可以是通过 super 进行显式调用,也可以是隐式调用。

当所有父类的非静态初始化块、构造器依次调用完成后,系统调用本类的非静态初始化块、构造器执行初始化,最后返回本类的实例。 下面程序演示了创建Java 对象时的初始化过程。

class Creature 
{ 
      { 
            System.out.println("Creature 的非静态初始化块"); 
      } 
      //下面定义两个构造器 
      public Creature() 
      { 
            System.out.println("Creature 无参数的构造器"); 
      } 
      public Creature(String name) 
      { 
            //使用 this 调用另一个重载、无参数的构造器 
            this(); 
            System.out.println("Creature 带有 name参数的构造器,name参数:" 
                  + name);  
      } 
} 
class Animal extends Creature 
{ 
      { 
            System.out.println("Animal的非静态初始化块"); 
      }
      public Animal(String name) 
      { 
            super(name); 
            System.out.println("Animal带一个参数的构造器,name 参数:" + name); 
      } 
      public Animal(String name , int age) 
      { 
            //使用 this 调用另一个重载的构造器 
            this(name); 
            System.out.println("Animal 带 2个参数的构造器,其age:" + age); 
      } 
} 
class Wolf extends Animal 
{ 
      { 
            System.out.println("Wolf 的非静态初始化块"); 
      } 
      public Wolf() 
      { 
            //显式调用父类有2个参数的构造器 
            super("灰太狼", 3); 
            System.out.println("Wolf 无参数的构造器"); 
      } 
      public Wolf(double weight) 
      { 
            //使用 this 调用另一个重载的构造器 
            this(); 
            System.out.println("Wolf 的带 weight 参数的构造器,weight 参数:" 
                  + weight); 
      } 
} 
public class InitTest 
{ 
      public static void main(String[] args) 
      { 
            new Wolf(5.6); 
      } 
}

上面程序定义了 Creature、Animal、Wolf 这 3 个类,其中 Animal 是 Creature 的子类,Wolf 是Animal 的子类。3个类都包含了非静态初始化块、构造器成分。当程序调用Wolf 的指定构造器创建Wolf 实例时,程序会按上面介绍的初始化步骤执行初始化。

只要在程序创建Java 对象,系统总是先调用最顶层父类的初始化操作,包括初始化块和构造器,然后依次向下调用所有父类的初始化操作,最终执行本类的初始化操作返回本类的实例。至于调用父类的哪个构造器执行初始化,则分为如下几种情况:

  • 子类构造器执行体的第一行代码使用super 显式调用父类构造器,系统将根据super调用里传入的实参列表来确定调用父类的哪个构造器;
  • 子类构造器执行体的第一行代码使用 this 显式调用本类中重载的构造器,系统将根据 this 调用里传入的实参列表来确定本类的另一个构造器(执行本类中另一个构造器时即进入第一种情况);
  • 子类构造器执行提中既没有super调用,也没有this 调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器。

super 调用用于显式调用父类的构造器,this 调用用于显式调用本类中另一个重载的构造器。super调用和this 调用都只能在构造器中使用,而且super 调用和this 调用都必须作为构造器的第一行代码,因此构造器中的super调用和this 调用最多只能使用其中之一,而且最多只能调用一次。

转载请注明:零五宝典 » Java中父类构造器的隐式调用和显式调用