杰瑞科技汇

构造方法中this()如何调用同类其他构造方法?

这是一个非常重要且常用的特性,它允许你在一个构造方法中调用同一个类的另一个构造方法

构造方法中this()如何调用同类其他构造方法?-图1
(图片来源网络,侵删)

this() 是什么?

this() 是 Java 中一个特殊的构造方法调用,它只能在构造方法的第一行使用,用于调用当前类的另一个构造方法。

它的主要目的是为了代码复用保证初始化逻辑的集中管理


为什么需要 this()

想象一下,你有一个 Person 类,它有多个属性,name, age, 和 gender,你可能想提供多种方式来创建一个 Person 对象:

  1. 只提供 name
  2. 提供 nameage
  3. 提供 name, age, 和 gender

如果不使用 this(),你的代码可能会是这样:

构造方法中this()如何调用同类其他构造方法?-图2
(图片来源网络,侵删)
public class Person {
    private String name;
    private int age;
    private String gender;
    // 构造方法1: 只提供 name
    public Person(String name) {
        this.name = name;
        // age 和 gender 默认为初始值 0 和 null
    }
    // 构造方法2: 提供 name 和 age
    public Person(String name, int age) {
        this.name = name; // 重复赋值
        this.age = age;
        // gender 默认为 null
    }
    // 构造方法3: 提供 name, age 和 gender
    public Person(String name, int age, String gender) {
        this.name = name; // 再次重复赋值
        this.age = age;
        this.gender = gender;
    }
    // ... 其他方法
}

问题所在:

  • 代码重复this.name = name; 这行代码在多个构造方法中重复出现。
  • 维护困难:如果将来 name 的初始化逻辑变得更复杂(需要首字母大写),你就需要修改所有包含这行代码的构造方法。

如何使用 this() 解决问题?

我们可以使用 this() 来重构上面的代码,核心思想是:让最“完整”的构造方法(参数最多的那个)负责所有属性的初始化,然后让其他“简单”的构造方法通过 this() 来调用这个“完整”的构造方法

重构后的代码如下:

public class Person {
    private String name;
    private int age;
    private String gender;
    // 构造方法3: "主构造方法" 或 "完整构造方法"
    // 它负责所有属性的初始化
    public Person(String name, int age, String gender) {
        System.out.println("调用 Person(String, int, String) 构造方法");
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    // 构造方法2: 提供默认 gender
    // 通过 this() 调用上面的完整构造方法
    public Person(String name, int age) {
        // this() 必须在构造方法的第一行!
        this(name, age, "未知"); // 传入一个默认的 gender 值
        System.out.println("调用 Person(String, int) 构造方法");
    }
    // 构造方法1: 提供默认 age 和 gender
    // 同样通过 this() 调用
    public Person(String name) {
        // this() 必须在构造方法的第一行!
        this(name, 0, "未知"); // 传入默认的 age 和 gender 值
        System.out.println("调用 Person(String) 构造方法");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
    public static void main(String[] args) {
        System.out.println("--- 创建 p1 ---");
        Person p1 = new Person("张三");
        System.out.println(p1);
        System.out.println("\n--- 创建 p2 ---");
        Person p2 = new Person("李四", 25);
        System.out.println(p2);
        System.out.println("\n--- 创建 p3 ---");
        Person p3 = new Person("王五", 30, "男");
        System.out.println(p3);
    }
}

输出结果:

构造方法中this()如何调用同类其他构造方法?-图3
(图片来源网络,侵删)
--- 创建 p1 ---
调用 Person(String) 构造方法
调用 Person(String, int, String) 构造方法
Person{name='张三', age=0, gender='未知'}
--- 创建 p2 ---
调用 Person(String, int) 构造方法
调用 Person(String, int, String) 构造方法
Person{name='李四', age=25, gender='未知'}
--- 创建 p3 ---
调用 Person(String, int, String) 构造方法
Person{name='王五', age=30, gender='男'}

分析:

  1. 当执行 new Person("张三") 时,它调用了 Person(String name) 构造方法。
  2. 这个构造方法的第一行是 this(name, 0, "未知");,于是它立即停止当前流程,转而去调用 Person(String name, int age, String gender) 构造方法。
  3. Person(String name, int age, String gender) 执行完毕后,返回到 Person(String name) 构造方法,继续执行 System.out.println(...)
  4. 同理,new Person("李四", 25) 会先调用 Person(String, int),再由它调用 Person(String, int, String)

这样,所有关于 name, age, gender 的初始化逻辑都集中在了最“完整”的构造方法中,代码变得清晰、简洁且易于维护。


this() 的核心规则

  1. 只能在构造方法内部使用this() 不能在普通方法(如 main 方法)或静态上下文中使用。
  2. 必须是第一条语句this() 调用必须放在构造方法的第一行,这是为了保证对象在调用其他构造方法之前,已经被部分或完全初始化,如果放在后面,Java 编译器会报错。
  3. 不能形成闭环:不能出现构造方法 A 调用 B,B 又调用 A 的情况,这会导致无限递归,最终抛出 StackOverflowError(栈溢出错误)。
  4. super() 互斥:一个构造方法的第一行,要么是 this(),要么是 super()(调用父类的构造方法),但不能同时出现,如果两者都没有,编译器会自动在第一行插入一个 super(),调用父类的无参构造方法。

this()super() 的区别

这是一个非常容易混淆的点,我们来对比一下:

特性 this() super()
含义 调用当前类的另一个构造方法。 调用父类的构造方法。
目的 在当前类内部复用构造方法的代码 初始化从父类继承来的成员变量,并完成父类的构造。
调用时机 this() 调用必须在 super() 调用之前。 super() 调用必须在构造方法的第一行(除非有 this())。
示例 this(name, age); super(name);

一个同时包含 this()super() 的例子:

class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
        System.out.println("Animal 构造方法被调用");
    }
}
class Dog extends Animal {
    private String breed;
    // Dog 的完整构造方法
    public Dog(String name, String breed) {
        // 1. 第一行调用父类的构造方法
        super(name); // 必须先调用父类的构造方法来初始化 name
        // 2. 然后初始化自己的成员变量
        this.breed = breed;
        System.out.println("Dog 完整构造方法被调用");
    }
    // Dog 的简化构造方法
    public Dog(String name) {
        // this() 必须在 super() 之后,所以这种写法是错误的!
        // this(name, "Unknown"); // 错误!
        // 正确的写法是直接调用 super(),然后自己处理
        super(name);
        this.breed = "Unknown";
        System.out.println("Dog 简化构造方法被调用");
    }
}

this() 是 Java 构造方法中的一个强大工具,它通过让一个构造方法调用另一个构造方法,实现了代码的复用和集中管理,使得类的构造逻辑更加清晰、健壮和易于维护,记住它的核心规则:只能在构造方法的第一行调用,用于调用同一个类的其他构造方法

分享:
扫描分享到社交APP
上一篇
下一篇