实例分析
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...)),JVM 就不再调用无参的super()。
结论3
如果没有任何构造函数,系统会默认有一个无参构造函数;一旦创建有参构造函数后,JVM 就不再有默认无参构造函数了。
官方JDK相关实例
就如我上一篇中的 Java IO 系列,其中的字符输入输出流抽象类Reader和Writer,它们的子类都会默认调用父类的无参构造方法来初始化Object lock属性,从而可以通过使用同步块的方式达到线程安全的目的。
评论区