实例分析

public class ParentTest {
  public ParentTest() {
    System.out.println("ParentTest 无参构造方法");
  }

  public ParentTest(String name) {
    System.out.println(name);
  }
}
public class ChildTest extends ParentTest {

  public ChildTest() {}

  public ChildTest(String name) {
    System.out.println(name);
  }

  public static void main(String[] args) {
    ChildTest test = new ChildTest("liveJQ");
  }
}

正常输出:

ParentTest 无参构造方法
liveJQ

若试着将ParentTest类中的无参构造方法注释掉,则不能编译,运行会产生如下异常:

错误: 无法将类 ParentTest中的构造器 ParentTest应用到给定类型;
    public ChildTest(){
                      ^
  需要: String
  找到: 没有参数
  原因: 实际参数列表和形式参数列表长度不同

  错误: 无法将类 ParentTest中的构造器 ParentTest应用到给定类型;
    public ChildTest(String name){
                                 ^
  需要: String
  找到: 没有参数
  原因: 实际参数列表和形式参数列表长度不同
2 个错误

FAILURE: Build failed with an exception.

所以可以得知,在初始化子类时,子类隐式调用了父类的无参构造方法,相当于:

  public ChildTest(String name) {
      // 必须是第1行,否则不能编译
    super();
    System.out.println(name);
  }

在创建子类的对象时,Java虚拟机首先执行父类的构造方法,然后再执行子类的构造方法。在多级继承的情况下,将从继承树的最上层的父类开始,依次执行各个类的构造方法,这可以保证子类对象从所有直接或间接父类中继承的实例变量都被正确地初始化。

结论1

Java 继承中对构造函数是不继承的,只是调用(隐式或显式)。

结论2

显式调用了super后(如super()或者super(参数1,参数2…)),系统就不再调用无参的super()

结论3

如果没有任何构造函数,系统会默认有一个无参构造函数;一旦创建有参构造函数后,系统就不再有默认无参构造函数了。

官方JDK相关实例

就如我上一篇中的 Java IO 系列,其中的字符输入输出流抽象类Reader和Writer,它们的子类都会默认调用父类的无参构造方法来初始化Object lock属性,从而可以通过使用同步块的方式达到线程安全的目的。

参考文章:java中子类继承父类时是否继承构造函数

  • IO流

    Java IO体系结构IO实际上分为阻塞型IO(Blocking IO)和非阻塞型IO(Non-Blocking IO 简称NIO) ...

    IO流
  • Java中的Enum关键字

    一般常量的定义方式 来自 Effective Java Edition 3 // The int enum pattern - s...

    Java中的Enum关键字
  • Try-With-Resources声明

    try-with-resources语句try-with-resources语句是一种声明了一种或多种资源的try语句。资源是指在程序...

    Try-With-Resources声明