最近在学习 Java 继承时,对构造方法的调用规则产生了一些疑问:如果父类没有无参构造会怎样?多级继承时要怎么处理?子类自身构造方法又会如何影响调用链?通过一番研究和实验,我整理了这篇笔记,分享给大家,希望能帮助到有同样困惑的小伙伴。
在 Java 中,当我们通过 new
创建一个对象时,构造方法的调用遵循以下规则:
super(...)
),Java 会自动调用父类的无参构造方法 super()
。但实际情况会因为父类和子类的构造方法定义而有所不同,下面我们逐步分析。
如果父类只定义了有参构造方法,没有无参构造方法,而子类构造方法没有手动调用父类的有参构造,会发生什么?
会报错!
子类构造方法默认会调用 super()
,但如果父类没有无参构造,编译器会提示错误,比如:“没有默认构造方法”。
解决办法:子类必须用 super(参数)
手动调用父类的有参构造。
class A {
public A(int x) { // 只有有参构造
System.out.println("A 的有参构造: " + x);
}
}
class B extends A {
public B() {
super(10); // 必须手动调用
System.out.println("B 的构造");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
}
}
A 的有参构造: 10
B 的构造
如果有多个父类(继承链),每个父类都没有无参构造,需要在子类中写多个 super
调用吗?
Java 是单继承,一个类只能直接继承一个父类,所以不存在 “多个父类” 的情况。
但如果是多级继承(比如 A ← B ← C
),需要沿着继承链逐级处理构造方法。
每个子类只需关心自己的直接父类,用 super(参数)
调用即可。
调用顺序依然是从最顶层父类开始,逐级向下。
class A {
public A(int x) {
System.out.println("A 的构造: " + x);
}
}
class B extends A {
public B(int x) {
super(x);
System.out.println("B 的构造");
}
}
class C extends B {
public C(int x) {
super(x);
System.out.println("C 的构造");
}
}
public class Main {
public static void main(String[] args) {
C c = new C(5);
}
}
A 的构造: 5
B 的构造
C 的构造
如果继承链上的每个类都有无参构造,创建子类对象时会发生什么?
Java 会自动调用每个类的无参构造,从最顶层父类到子类。
调用次数 = 继承链上的类总数(包括子类本身)。
class A {
public A() {
System.out.println("A 的无参构造");
}
}
class B extends A {
public B() {
// 自动调用 super()
System.out.println("B 的无参构造");
}
}
class C extends B {
public C() {
// 自动调用 super()
System.out.println("C 的无参构造");
}
}
public class Main {
public static void main(String[] args) {
C c = new C();
}
}
A 的无参构造
B 的无参构造
C 的无参构造
如果子类只定义了有参构造,没有无参构造,会影响构造链吗?
子类没有无参构造时,必须用有参方式创建对象(比如 new C(10)
)。
但构造链依然会从父类开始,父类的构造方法(无参或有参)依然会被调用。
class A {
public A() {
System.out.println("A 的无参构造");
}
}
class B extends A {
public B() {
// 自动调用 super()
System.out.println("B 的无参构造");
}
}
class C extends B {
public C(int x) { // 只有有参构造
// 自动调用 super()
System.out.println("C 的有参构造: " + x);
}
}
public class Main {
public static void main(String[] args) {
C c = new C(10);
}
}
A 的无参构造
B 的无参构造
C 的有参构造: 10
用 super
主动调用父类的有参构造方法,会不会再调用无参构造方法?
不会。只要子类显式调用了 super(参数)
,编译器就不会再自动调用父类的无参构造方法。父类的构造方法在一次对象创建中只会被调用一次。
class Parent {
public Parent() {
System.out.println("父类无参构造");
}
public Parent(String s) {
System.out.println("父类有参构造: " + s);
}
}
class Child extends Parent {
public Child() {
super("Test"); // 显式调用有参构造
System.out.println("子类构造");
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
}
}
父类有参构造: Test
子类构造
super()
)。super(参数)
手动调用,否则报错。super(参数)
调用父类的有参构造方法时,编译器不会再自动调用父类的无参构造方法。在一次对象创建过程中,父类的构造方法仅会被调用一次。