1. 概述

Java 是一种面向对象的语言,这意味着我们在初始化对象时必须处理构造函数。

Project Lombok 可以通过为不同类型的构造函数使用不同的注解,帮助我们简化代码生成,减少编写样板代码的工作量。

在这个教程中,我们将探讨如何使用 @RequiredArgsConstructor 注解来自动为我们的类生成构造函数。

2. 配置

要在项目中使用 Project Lombok,请在 pom.xml 文件中添加依赖:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

3. 使用

@RequiredArgsConstructor 是一个 Lombok 注解,它会为所有 final 和非 null 的字段自动生成构造函数。

在示例中,我们将定义具有不同作用域成员变量的类,并观察注解在不同场景下的行为。

3.1. final 字段

final 字段是在构造函数完成前一次性初始化的类成员。

让我们定义一个带有 final 字段的类,然后测试 @RequiredArgsConstructor 注解:

@RequiredArgsConstructor
public class ClassWithFinalMembers {

    private final String stringObject;

    // standard getters
}

@RequiredArgsConstructor 注解会生成一个带有 final 成员的参数化构造函数。现在,我们执行一个简单的测试来成功初始化上述类:

@Test
void whenClassHasFinalMembers_thenGeneratedConstructorHasParameters() {
    ClassWithFinalMembers classWithFinalMembers = new ClassWithFinalMembers("dummyString");
    Assertions.assertNotNull(classWithFinalMembers);
    Assertions.assertEquals("dummyString", classWithFinalMembers.getStringObject());
}

3.2. 非 final 字段

当类有非 final 字段时,@RequiredArgsConstructor 注解在生成代码时不将它们添加到构造函数参数中。

如果没有 final 或非 null 字段,只有非 final 字段,那么我们将会得到一个无参数的构造函数。

让我们看看上述情况的一个例子,并通过简单测试用例验证:

@RequiredArgsConstructor
public class ClassWithNonFinalMembers {

    private String stringObject;

    // standard getters
}
@Test
void whenClassHasNonFinalMembers_thenGeneratedConstructorHasNoParameters() {
    ClassWithNonFinalMembers classWithNonFinalMembers = new ClassWithNonFinalMembers();
    Assertions.assertNotNull(classWithNonFinalMembers);
}

我们定义了一个类,其中包含一个非 final 成员,因此使用 @RequiredArgsConstructor 不会在生成的构造函数参数中包含该成员。如果我们尝试使用参数化构造函数,编译器会抛出错误。

3.3. 非 null 字段

要为包含非 null 字段生成构造函数,我们可以使用 @NonNull Lombok 注解:

@RequiredArgsConstructor
public class ClassWithFinalNonNullMembers {

    private final String finalStringObject;
    @NonNull
    private String nonNullStringObject;

    private String nonFinalStringObject;

    // standard getters
}

现在,让我们看一个简单的测试用例:

@Test
void whenClassHasFinalAndNonNullMembers_thenGeneratedConstructorHasParameters() {
    ClassWithFinalNonNullMembers classWithFinalNonNullMembers = new ClassWithFinalNonNullMembers("finalString", "nonNullString");
    Assertions.assertNotNull(classWithFinalNonNullMembers);
    Assertions.assertEquals("finalString", classWithFinalNonNullMembers.getFinalStringObject());
    Assertions.assertEquals("nonNullString", classWithFinalNonNullMembers.getNonNullStringObject());
    Assertions.assertNull(classWithFinalNonNullMembers.getNonFinalStringObject());
}

我们定义了一个类,包含 final、非 null 和非 final 成员。因此,@RequiredArgsConstructor 注解会生成构造函数,除了初始化 final 成员外,还会初始化非 null 成员。

4. 总结

在这篇文章中,我们了解了 @RequiredArgsConstructor 如何生成构造函数来初始化类的成员。

final 成员和标记为 @NonNull 的成员会被包含在构造函数参数和定义中。然而,既不是 final 也不是标记为 @NonNull 的成员不会被生成的构造函数初始化。

如往常一样,所有示例的源代码可以在 GitHub 上找到。