微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 Java Records 有访问器方法而不是公共 final 字段?

如何解决为什么 Java Records 有访问器方法而不是公共 final 字段?

JEP-395

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

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

如果生成的 final 字段与访问器方法同名,为什么不生成公共 final 字段呢?


记录组件几乎不会被仔细地更改,因为记录类的实例可以被序列化和反序列化。但是,不能通过提供 writeObject、readobject、readobjectNoData、writeExternal 或 readExternal 方法自定义流程

因此更改 API 内部实现(记录组件)不是合适的理由。但我有充分的理由来自 @Brian Goetz

谢谢大家关注我的傻问题

解决方法

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

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

引用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 Goetzthis answer 的评论中提供了另一个原因:

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

,

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

,

我认为做出此决定的一个关键因素是您现在可以覆盖记录的 getter:

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。