3

探秘Java语言中子类调用父类的构造方法的方式

 11 months ago
source link: https://blog.51cto.com/sunweiqin/7871402
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

探秘Java语言中子类调用父类的构造方法的方式

精选 原创

孙卫琴书友会 2023-10-15 12:46:42 博主文章分类:Java编程 ©著作权

文章标签 构造方法 父类 java 文章分类 Java 后端开发 阅读数246

父类的构造方法不能被子类继承。假定Base父类有以下构造方法:

public Base(Srting msg){
  this.msg=msg;
}

以下Sub类继承了Base类:

public class Sub extends Base{}

以上Sub类有一个隐含的默认构造方法,形式如下:

public Sub(){}

尽管在Base父类中定义了如下形式的构造方法:

public Base(String msg)

但Sub类不会继承Base类的构造方法,因此以下代码是不合法的:

//非法,Sub类不存在这样的构造方法
Sub b=new Sub("Hello");

在子类的构造方法中,可以通过super语句调用父类的构造方法。例如:

public class Sub extends Base{
  public Sub(){
    //调用Base父类的Base(String msg)构造方法
    super("Hello");
  }

  public Sub(String msg){
    //调用Base父类的Base(String msg)构造方法
    super(msg);
  } 
}

假如在子类的构造方法中有super语句,它必须作为构造方法的第一条语句(不考虑注释语句),以下代码是非法的:

public Sub(){
  String msg= "Hello";
  super(msg);       //非法,super语句必须作为构造方法的第一条语句
}

在通过new语句创建子类的实例时,Java虚拟机首先执行父类的构造方法,再执行子类的构造方法。在多级继承的情况下,将从继承树的最上层的父类开始,依次执行各个类的构造方法。

探秘Java语言中子类调用父类的构造方法的方式_构造方法

大力向卫琴请教创建子类对象,先调用父类构造方法的意义

探秘Java语言中子类调用父类的构造方法的方式_父类_02

创建子类实例时,先调用父类构造方法,再调用子类构造方法

在例程1的Base.java和Sub.java中,Base父类和Sub子类分别有一个实例变量a和b,当创建Sub类的实例时,这两个实例变量都会被初始化。

例程1 Base.java和Sub.java

/** Base.java */
package mypack4;
public class Base{
  int a;
  public Base(int a){ this.a=a;}
}

/** Sub.java */
package mypack4;
public class Sub extends Base{
  int b;
  public Sub(int a,int b){
    super(a);                          //初始化父类的实例变量a
    this.b=b;                          //初始化子类的实例变量b
  }
  
  public static void main(String args[]){
    Sub sub=new Sub(1,2);
    System.out.println(sub.a+","+sub.b);       //打印1,2
  }
}

大力:“如果子类的构造方法没有通过super语句调用父类的构造方法,那会怎么样呢?”

卫琴姐:“此时Java虚拟机会自动先调用父类的不带参数的构造方法。”

在例程2的Base.java和Sub.java中,Base类有一个不带参数的构造方法。Sub类的Sub(int i)构造方法没有用super语句调用父类的构造方法,因此当创建Sub类的实例时,会先自动调用Base父类的不带参数的构造方法。

例程2 Base.java和Sub.java

/** Base.java */
package mypack5;
public class Base{
  public Base(){             //不带参数的构造方法
    System.out.println("call Base()");
  }
}  

/** Sub.java */
package mypack5;
public class Sub extends Base{
  public Sub(){
    System.out.println("call Sub()");
  }

  public static void main(String args[]){
    Sub b=new Sub();  
  }
}

运行Sub类,会得到以下打印结果:

call Base()
call Sub()

如果把Base类的不带参数的构造方法改为:

public Base(int a){}        //带参数的构造方法

编译Sub类时会出错, 因为Base父类中没有可以被Sub类自动调用的不带参数的构造方法。一种修改方式为:在Sub类的构造方法中,通过super语句显式调用父类的构造方法:

public Sub(){
  super(1);          //调用Base父类的Base(int a)构造方法
  System.out.println("call Sub()");
}

上文参考孙卫琴的经典Java书籍《Java面向对象编程》

探秘Java语言中子类调用父类的构造方法的方式_java_03

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK