✅ 1. super()
是什么?
super();
表示:在子类构造函数中,显示调用父类的构造函数。
它只能写在子类构造函数的第一行,如果你不写,Java 编译器会默认加上 super()
(调用父类的无参构造函数)。
🔍 2. 它的本质原理是什么?(编译器 & JVM 角度)
🔧 编译阶段(Java 编译器):
当你写:
public class Child extends Parent {
public Child() {
super(); // 编译器会自动加这句(如果你没写)
System.out.println("Child constructor");
}
}
编译器在生成 .class
字节码时,会在构造函数开头加上对 Parent
构造方法的调用。
🧠 JVM 层面(字节码执行):
字节码会这样表示(伪代码):
aload_0 // this 入栈
invokespecial #1 // 调用父类构造函数 <init>
invokespecial
是字节码指令,用来调用构造函数或私有方法。#1
是常量池中的父类构造函数引用。
JVM 在运行时会用你传的参数,去调用父类的构造方法,确保父类部分初始化完成。
🔄 为什么必须调用父类构造函数?
Java 的对象初始化过程是自底向上的:
- 子类对象中包含父类部分;
- 所以必须先初始化父类成员;
- 只有父类构造函数执行完,子类构造函数才可以执行。
否则:子类使用了父类中的成员,却还没初始化,会导致运行错误或未定义行为。
❗ 特别注意
✅ 自动调用 super()
class Parent {
public Parent() {
System.out.println("Parent()");
}
}
class Child extends Parent {
public Child() {
System.out.println("Child()");
}
}
等价于:
public Child() {
super(); // 编译器自动添加
System.out.println("Child()");
}
❌ 没有父类无参构造怎么办?
class Parent {
public Parent(String name) {}
}
class Child extends Parent {
public Child() {
// ❌ 编译错误!找不到 super()
}
}
父类没有无参构造函数时,子类必须在构造函数中显式调用带参数的
super(name)
。
✅ 总结一句话
点 | 内容 |
---|---|
super() 是什么 | 调用父类的构造函数 |
为什么必须调用 | 因为子类对象包含父类部分,必须先初始化父类 |
本质机制 | 编译器在构造函数第一行加 invokespecial 指令,调用父类 <init> |
默认行为 | 如果你没写,编译器会加 super() ,前提是父类有无参构造 |