1. 概述

在这个简短的教程中,我们将学习如何在Java中链式构造函数。这是一种便捷的设计模式,可以减少重复代码并提高可读性。

首先,我们会解释什么是构造函数链,并演示如何在同一类中链式调用它们以及如何从父类中使用构造函数。最后,我们会分析这种做法的优缺点。

2. 链式构造函数定义及其示例

构造函数链是指按照顺序调用一系列构造函数的过程。有两种方式实现:

  • 在同一类中使用this()关键字进行链式调用
  • 从父类中使用super()关键字进行链式调用

让我们分别看看这两种方法的例子。

2.1. 同一类内的构造函数链

我们定义一个简单的Person类,包含一些属性:

public class Person {
    private final String firstName;
    private final String middleName;
    private final String lastName;
    private final int age;

    //getters, equals and hashcode
}

firstNamelastNameage是我们想在对象初始化时始终设置的属性。但并非每个人都有中间名,因此middleName属性是可选的。

考虑到这一点,我们将创建两个构造函数。第一个接受所有四个属性:

public Person(String firstName, String middleName, String lastName, int age) {
    this.firstName = firstName;
    this.middleName = middleName;
    this.lastName = lastName;
    this.age = age;
}

第二个构造函数将接受三个必需的属性,跳过可选字段:

public Person(String firstName, String lastName, int age) {
    this(firstName, null, lastName, age);
}

我们使用this()关键字。它必须始终是构造函数的第一行,确保要链接到的构造函数首先被调用。

请记住,类中构造函数的顺序无关紧要。这意味着我们的第二个构造函数可以放在Person类的任何位置,仍然能正确工作。

2.2. 从父类的构造函数链

现在,我们定义一个Customer类,它继承自上一节中创建的Person类:

public class Customer extends Person {
    private final String loyaltyCardId;

   //getters, equals and hashcode
}

它增加了一个额外的属性。接下来,我们像在Person类中那样创建两个构造函数:

public Customer(String firstName, String lastName, int age, String loyaltyCardId) {
    this(firstName, null, lastName, age, loyaltyCardId);
}

public Customer(String firstName, String middleName, String lastName, int age, String loyaltyCardId) {
    super(firstName, middleName, lastName, age);
    this.loyaltyCardId = loyaltyCardId;
}

第一个构造函数使用this()关键字链接到第二个构造函数,该构造函数接受所有必需和可选属性。这里首次使用了super()关键字。

它的行为与this()关键字非常相似。唯一的区别是,super()链接到父类中的对应构造函数,而this()链接到同一类中的构造函数。

同样,super()也必须始终作为构造函数的第一行。这意味着首先调用父类的构造函数,然后将值赋给loyaltyCardId属性。

3. 链式构造函数的优缺点

链式构造函数的最大优点是减少了代码重复。换句话说,我们遵循“不要重复自己”(DRY)原则。这是因为我们在单个构造函数(通常接受所有属性的那个)中完成对象的初始化。其他构造函数的作用是传递接收到的数据,并为缺失的属性添加默认值。

链式构造函数使代码更易于阅读。我们不必在所有构造函数中重复属性赋值。相反,这些操作在一个地方完成。

另一方面,使用链式构造函数时暴露了更多的对象构建方式,这在某些项目中可能是显著的缺点。在这种情况下,我们应该考虑使用工厂模式构建者模式来隐藏多个构造函数。

4. 总结

本文讨论了Java中的构造函数链。首先解释了构造函数链的概念,然后展示了如何在同一类中以及通过父类构造函数实现链式调用。最后,我们讨论了链式构造函数的优点和缺点。

如往常一样,文章的完整源代码可以在GitHub上找到:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-lang-4