在Java中,super()
和 this()
都是用于构造函数中调用其他构造函数的语句,但它们的用途和调用对象不同。以下是它们的详细用法和区别:
1. super()
- 作用:调用父类的构造函数。
- 用法:
- 子类构造函数中通过
super()
显式调用父类的构造函数。 - 如果子类构造函数中没有显式调用
super()
,编译器会默认调用父类的无参构造函数(即super()
)。 super()
必须是构造函数中的第一条语句(否则编译错误)。
- 子类构造函数中通过
- 适用场景:
- 父类没有无参构造函数时,子类必须显式调用
super(参数)
。 - 需要在子类中初始化父类的成员变量或执行父类的初始化逻辑。
- 父类没有无参构造函数时,子类必须显式调用
示例:
class Parent {
Parent(int x) {
System.out.println("Parent constructor: " + x);
}
}
class Child extends Parent {
Child() {
super(10); // 显式调用父类的有参构造函数
System.out.println("Child constructor");
}
}
2. this()
- 作用:调用当前类的其他构造函数(重载的构造函数)。
- 用法:
- 用于在同一个类中复用构造函数代码。
this()
必须是构造函数中的第一条语句(否则编译错误)。- 不能和
super()
同时出现在同一个构造函数中。
- 适用场景:
- 避免重复代码,通过一个主构造函数处理初始化逻辑,其他构造函数调用它。
示例:
class Person {
String name;
int age;
Person() {
this("Unknown", 0); // 调用当前类的有参构造函数
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
3. super()
和 this()
的关键区别
特性 | super() |
this() |
---|---|---|
调用目标 | 父类的构造函数 | 当前类的其他构造函数 |
默认行为 | 子类默认调用 super() (无参) |
无默认行为,需显式调用 |
是否必须第一条语句 | 是 | 是 |
能否同时使用 | 不能与 this() 共存 |
不能与 super() 共存 |
4. 注意事项
-
隐式调用:
- 如果子类构造函数既没有
super()
也没有this()
,编译器会自动插入super()
(调用父类无参构造函数)。 - 如果父类没有无参构造函数,子类必须显式调用
super(参数)
。
- 如果子类构造函数既没有
-
链式调用:
- 构造函数调用链最终必须指向父类构造函数(因为所有类继承自
Object
)。
- 构造函数调用链最终必须指向父类构造函数(因为所有类继承自
-
错误示例:
class A { A(int x) {} } class B extends A { B() { // 编译错误:父类没有无参构造函数,且未显式调用 super(int) } }
5. 综合示例
class Animal {
String type;
Animal(String type) {
this.type = type;
}
}
class Dog extends Animal {
String name;
Dog() {
this("Unknown"); // 调用当前类的有参构造函数
}
Dog(String name) {
super("Canine"); // 调用父类的构造函数
this.name = name;
}
}
通过合理使用 super()
和 this()
,可以高效地管理类的构造函数逻辑和继承关系。