-2

JEP-395

记录类自动获取许多标准成员:

  • 对于header中的每个组件,有两个成员:一个与组件同名和返回类型的公共访问器方法,以及一个与组件同类型的私有final字段;

如果生成的最终字段与访问器方法具有相同的名称,为什么不生成公共最终字段呢?


由于记录类的实例可以序列化和反序列化,因此记录组件几乎不会被仔细更改。但是,无法通过提供 writeObject、readObject、readObjectNoData、writeExternal 或 readExternal 方法来自定义流程

所以改变 API 内部实现(记录组件)不是一个合适的理由。但我从@Brian Goetz那里得到了充分的理由

谢谢大家关注我的傻问题

4

3 回答 3

6

记录可以实现接口,因此记录的访问者可以是接口方法的实现。此外,使用访问器而不是直接字段访问提供了更大的灵活性,例如,您可以将直接返回字段的访问器替换为以某种方式派生值的访问器(反之亦然)。

记录还允许您覆盖访问器 - 而不仅仅是简单地返回字段 - 做一些额外的事情。使记录使用直接字段访问将限制和限制您可以对记录执行的操作,从而限制它们的有用性,而让访问者为您提供直接字段访问提供的基线,并在必要时能够做更多的事情。

引用Holger在评论中提供的示例:

public record R(int a, int b) { public int c() { return …; }}public record R(int a, int c) { public int b() { return …; }}提供相同的 API,而不管它们的内部表示如何。

简而言之,为字段生成访问器提供了比直接字段访问更多的灵活性和功能。这同样适用于普通的不可变类。

Brian Goetz对此答案的评论中提供了另一个原因:

如果没有覆盖访问器的能力,记录将无法正确支持可变对象(例如数组)作为组件。如果您有一个数组组件,您可能希望在构造函数和访问器中执行防御性复制(这也需要覆盖 equals,以保留 Record 的规范);如果它是公共 final 字段,则无法封装组件的可变性

于 2021-03-19T08:47:13.107 回答
2

我认为这个决定的一个关键因素是你现在有能力覆盖Record 的 getter:

public record MyRecord(String myProperty) {
    @Override
    public String myProperty() {
        return "The property is " + myProperty;
    }
}

对于公共最终字段,这样的事情是不可能的。

于 2021-03-19T07:56:25.260 回答
0

通常最好的做法是使用访问器方法而不是直接字段访问。即使有记录,继续这种做法也很有意义,例如,在不破坏现有代码的情况下重命名字段。

于 2021-03-19T03:42:56.633 回答