Java this() 调用同类构造方法
1. 核心语法规则
在构造方法内部使用
this(参数列表)调用本类其他构造方法时,this()必须写在构造方法的第一行,否则编译报错。
编译错误信息:
Constructor call must be the first statement in a constructor
2. 为什么必须放在第一行
Java 对象初始化有固定流程:
- 优先完成父类初始化(
super()) - 再执行本类实例初始化
this() 的作用:委托本类另一个构造方法完成对象初始化;被调用的构造内部会自动执行父类构造 super()。
设计目的 :保证对象完整初始化完毕后,再执行当前构造的业务逻辑。如果允许写在中间,会出现对象成员尚未初始化,就执行读写实例变量,造成对象状态错乱。
通俗类比:盖房子先打地基,再砌墙装修。this() 委托别的构造完成地基与主体,所以必须最先执行。
3. 关键约束
this()只能在构造方法中使用 ,普通成员方法不能调用this()。this()与super()互斥,不能同时出现在同一个构造方法,两者都要求第一行。- 构造方法既不写
this(),也不写super(),编译器自动在第一行插入super(),调用父类无参构造。 - 禁止构造方法循环互相调用,运行时抛出
StackOverflowError栈溢出。
4. 代码示例
4.1 正确示例:this() 在第一行
java
public class Person {
private String name;
private int age;
// 无参构造
public Person() {
this("默认名称", 18); // 调用本类全参构造,必须第一行
System.out.println("无参构造执行");
}
// 单参构造
public Person(String name) {
this(name, 0); // 调用本类全参构造,必须第一行
System.out.println("单参构造执行");
}
// 全参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("全参构造执行");
}
public static void main(String[] args) {
Person p = new Person();
}
}
执行流程:
new Person() → 进入无参构造 → this("默认名称",18) → 执行全参构造 → 返回无参构造继续向下执行。
4.2 错误示例:this() 不在第一行,编译失败
java
public class Person {
private String name;
public Person() {
System.out.println("执行逻辑");
this("默认名称"); // ❌编译报错,不能放在其他语句之后
}
public Person(String name) {
this.name = name;
}
}
5. this. 和 this() 对比
| 写法 | 含义 | 使用位置 |
|---|---|---|
this.成员名 |
访问当前对象实例成员 | 构造方法、普通成员方法 |
this(参数列表) |
调用本类其他构造方法 | 仅构造方法,强制第一行 |
6. this() 与 super() 对比
6.1 核心区别
| 对比项 | this(参数列表) |
super(参数列表) |
|---|---|---|
| 调用目标 | 本类的其他构造方法 | 父类的构造方法 |
| 作用 | 复用本类构造逻辑,避免重复代码 | 初始化父类成员,完成父类部分构建 |
| 使用位置 | 仅构造方法内 | 仅构造方法内 |
| 是否强制第一行 | 是 | 是 |
| 能否共存 | 与 super() 互斥,不能同时出现 |
与 this() 互斥,不能同时出现 |
| 不写时编译器行为 | 不会自动插入 | 自动在第一行插入 super()(父类无参构造) |
| 查找范围 | 本类重载构造 | 父类(含间接父类)构造 |
6.2 代码示例对比
this() 示例:调用本类其他构造
java
public class Person {
private String name;
private int age;
public Person() {
this("未知", 0); // 调用本类全参构造
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
super() 示例:调用父类构造
java
public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类 Person 的有参构造
this.school = school;
}
public Student() {
// 不写 super(),编译器自动插入 super(),调用父类无参构造
this.school = "未知学校";
}
}
6.3 为什么互斥
this() 和 super() 都必须是构造方法的第一条语句,而第一条语句只能有一个,因此二者天然互斥。
- 写了
this()→ 跳转到本类另一个构造,那个构造内部会再执行super(),父类初始化不会遗漏。 - 写了
super()→ 直接完成父类初始化,再执行当前构造逻辑。 - 都不写 → 编译器自动补
super()。
6.4 初始化执行链示例
java
class Animal {
public Animal() {
System.out.println("Animal 构造");
}
}
class Dog extends Animal {
public Dog() {
this("默认名字"); // 调用本类有参构造
System.out.println("Dog 无参构造");
}
public Dog(String name) {
// 编译器自动插入 super(),调用 Animal 无参构造
System.out.println("Dog 有参构造:" + name);
}
}
// new Dog() 执行顺序:
// 1. Dog 无参构造 → this("默认名字")
// 2. Dog 有参构造 → 自动 super() → Animal 构造
// 3. Dog 有参构造剩余逻辑
// 4. 返回 Dog 无参构造剩余逻辑
// 输出:
// Animal 构造
// Dog 有参构造:默认名字
// Dog 无参构造
7. 总结
this(...)调用同类构造,语法强制位于构造方法第一行。super(...)调用父类构造,同样强制第一行;不写时编译器自动补super()。this()和super()互斥,不能共存于同一个构造。- 底层目的:严格保证对象初始化顺序(父类 → 本类),避免对象处于非法未初始化状态。
- 警惕构造循环调用,防止栈溢出。