使用新的Java 14记录功能,是否可以为同一记录创建多个构造函数?

huangapple go评论77阅读模式
英文:

With the new Java 14 Record functionality, is it possible of creating multiples constructors for the same Record?

问题

我有一堆使用 Lombok 的“data”类,我想将它们全部迁移到 Java 14 中提供的新 Record 功能。使用新的 Java 14 Record 功能,是否可以为同一记录创建多个构造函数?如果不行,是否有替代方法?

英文:

I have a bunch of "data" classes using Lombok and I want to migrate all of them to use the new Record functionality available in Java 14. With the new Java 14 Record functionality, is it possible of creating multiples constructors for the same Record? If not, is there an alternative?

答案1

得分: 14

使用Java 14,记录(records)不能有多个构造函数(参考:Java 14 - JEP 359: Records(预览版))。

从Java 15和16+开始,记录(records)可以有多个构造函数(参见Java 15 - JEP 384: Records(第二次预览)Java 16 - JEP 395: Records(最终版))。

然而,每个构造函数__必须委托给记录的规范构造函数__,规范构造函数可以明确定义或自动生成。

示例:

public record Person(
    String firstName,
    String lastName
) {
    // 紧凑的规范构造函数:
    public Person {
        // 仅进行验证;字段会自动赋值。
        Objects.requireNonNull(firstName);
        Objects.requireNonNull(lastName);

        // 显式字段赋值,例如:
        //   this.firstName = firstName;
        // 在紧凑形式的规范构造函数中会导致语法错误
    }

    public Person(String lastName) {
        // 其他构造函数必须直接委托给规范构造函数,
        // 可以直接调用:
        this("John", lastName);
    }

    public Person() {
        // ... 或者间接委托:
        this("Doe");
    }
}

另一个示例:

public record Person(
    String firstName,
    String lastName
) {
    // 规范构造函数没有在代码中定义,
    // 因此编译器会隐式生成它。

    public Person(String lastName) {
        // 其他构造函数仍然必须委托给规范构造函数!
        // 这样写是可以的:
        this("John", lastName);

        // 在这里直接重新赋值字段会导致编译错误:
        // this.lastName = lastName; // 错误:变量 'lastName' 可能已经被赋值
    }

    public Person() {
        // 委托给Person(String),进而委托给规范构造函数:
        this("Doe");
    }
}
英文:

With Java 14, records couldn't have multiple constructors (reference: Java 14 - JEP 359: Records (Preview)).

As of Java 15 and 16+, records may have multiple constructors.
(see Java 15 - JEP 384: Records (Second Preview) and Java 16 - JEP 395: Records (Final)).

However, every constructor must delegate to the record's canonical constructor which can be explicitly defined or auto-generated.

An example:

public record Person(
    String firstName,
    String lastName
) {
    // Compact canonical constructor:
    public Person {
        // Validations only; fields are assigned automatically.
        Objects.requireNonNull(firstName);
        Objects.requireNonNull(lastName);

        // An explicit fields assignment, like
        //   this.firstName = firstName;
        // would be a syntax error in compact-form canonical constructor
    }

    public Person(String lastName) {
        // Additional constructors MUST delegate to the canonical constructor,
        // either directly:
        this("John", lastName);
    }

    public Person() {
        // ... or indirectly:
        this("Doe");
    }
}

Another example:

public record Person(
    String firstName,
    String lastName
) {
    // Canonical constructor isn't defined in code, 
    // so it is generated implicitly by the compiler.

    public Person(String lastName) {
        // Additional constructors still MUST delegate to the canonical constructor!
        // This works: 
        this("John", lastName);

        // (Re-)Assigning fields here directly would be a compiler error:
        // this.lastName = lastName; // ERROR: Variable 'lastName' might already have been assigned to
    }

    public Person() {
        // Delegates to Person(String), which in turn delegates to the canonical constructor: 
        this("Doe");
    }
}

huangapple
  • 本文由 发表于 2020年8月27日 05:14:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63605831.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定