我想知道如何重写这节课

public class ClassA {
    private final String foo;
    private final String bar;

    public ClassA(String foo) {
        this.foo = foo;
        this.bar = foo.toUpperCase();
    }

    // getters...
}

as a record class.
The best I've managed to do is this

public record ClassA(String foo, String bar) {
    public ClassA(String foo) {
        this(foo, foo.toUpperCase());
    }
}

问题是这个解决方案创建了两个构造函数,而我只需要一个接受字符串foo的构造函数

推荐答案

记录类总是有一个所谓的canonical constructor,它需要为您声明的所有字段提供参数.默认情况下,该构造函数将由编译器生成,但您可以提供自己的构造函数,关键是:在运行时,每个记录都可以使用canonical constructor.

以下是Java Language Specification人的一句话:

为了确保其记录组件的正确初始化,记录类不会隐式声明默认构造函数(§8.8.9).相反,record class有一个canonical constructor,显式或隐式声明为记录类的101.

所有non-canonical constructors都是具有不同于canonical的签名的构造函数,就像您的 case 构造函数期望一个参数ClassA(String)一样,应该使用所谓的explicit constructor invocation(即使用this())将调用委托给canonical constructor(正如您所做的那样),否则此类构造函数将无法编译.

记录声明可以包含非规范构造函数的构造函数声明.出现记录声明102(§8.8.7.1)中的101,或编译时错误.

100由于您声明了一个包含two个字段的记录,并且您还需要一个non-canonical构造函数,该构造函数需要one个参数,因此将有两个构造函数:canonicalnon-canonical.没有解决方法.


101,正如@Brian Goetz正确指出的那样,canonical constructor也值得override.否则,由于可能使用具有不同逻辑的两个构造函数,记录的第二个参数是否为第一个参数的大写版本将存在歧义.

如果我们将记录定义如下:

public record ClassA(String foo, String bar) {
    public ClassA(String foo) {
        this(foo, foo.toUpperCase(Locale.ROOT));
    }
}

代码如下:

System.out.println(new ClassA("foo", "arbitrary string which not FOO"));
System.out.println(new ClassA("foo"));

将产生输出:

ClassA[foo=foo, bar=arbitrary string which not FOO] // unexpected result
ClassA[foo=foo, bar=FOO]                            // desired result

为了确保第二个参数在任何情况下都等于第一个变为大写的参数,我们必须覆盖canonical constructor:

public record ClassA(String foo, String bar) {
    public ClassA(String foo) {
        this(foo, foo); // doesn't matter what would be provided as the second argument
    }
    
    public ClassA(String foo, String bar) {
        this.foo = foo;
        this.bar = foo.toUpperCase(Locale.ROOT);
    }
}

Java相关问答推荐

编译期间错误(Java 0000)Android .Net MAUI

Annotation @ Memphier无法正常工作,并表示:class需要一个bean,但找到了2个bean:

Java Streams在矩阵遍历中的性能影响

Java:根据4象限中添加的行数均匀分布行的公式

Oracle DUAL表上使用DDL时jOOQ问题的解析'

Java自定义ThreadPool—暂停任务提交并取消当前排队任务

ittext pdf延迟签名,签名无效

neo4j java驱动程序是否会在错误发生时自动回滚事务?

如何确定springboot在将json字段转换为Dto时如何处理它?

放气总是压缩整个街区吗?

如何在EXCEL单元格中添加形状和文本

我如何解释这个错误?必需类型:供应商R,提供:收集器对象,捕获?,java.util.List java.lang.Object>>

在执行流和相关操作时,使用Java泛型为2个方法执行相同的操作,但对象不同

try 从REST API返回对象列表时出错

向Java进程发送`kill-11`会引发NullPointerException吗?

使IntelliJ在导入时优先 Select 一个类或将另一个标记为错误

在ECLIPSE上的M1 Pro上运行JavaFX的问题

控制器建议异常处理

Java泛型方法重载

Jackson YAML:支持锚点扩展/覆盖