在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(),可以高效地管理类的构造函数逻辑和继承关系。