JDK 16 记录、构造函数和随时间增加的内容?

问题描述

我对使用新的 JDK 16 记录很感兴趣,但是当我尝试创建一个具有附加参数的新记录时,出现错误

public record DrivePacket(Path drivePath,long driveSize) {
        public DrivePacket(Path drivePath,long driveSize) {
            this.drivePath = drivePath;
            this.driveSize = driveSize;
        }
        public DrivePacket(Path drivePath,long driveSize,String ID) {
            this(drivePath,driveSize);
            this.id = id;
        }
}

记录仅用于没有任何可变性的对象,还是可以随着时间的推移而扩展?

我对此类类有一个新要求(特别是意外添加了通过 NFS 共享的驱动器类型“远程”驱动器。

我发现自己试图想出一些方案,例如使用 driveSize 来指示“远程”状态,但这正是开发枚举的原因。

这种情况我该怎么办?我可以向构造函数添加选项并将它们存储在私有 final 字段中吗?或者我应该创建一个 DrivePacket -> RemoteDrivePacket 的子类,还是我应该为 RemoteDrivePacket 创建一个标记接口?

开发人员打算使用它的典型方式是什么?

解决方法

它们不能被子类化,也不能有“单独添加”意义上的字段,但你可以简单地在那里扔一个新属性; public record DrivePacket(Path drivePath,long driveSize,String id) {} 工作正常。

当然,现在所有创建新 DrivePacket 对象的代码都需要更新。您应该能够添加一个自定义构造函数,例如填充一些默认值。

如果您希望它们可构建、可扩展、具有非最终字段等,请查看 lombok's @Value。 (免责声明:我确实在 lombok 上工作)。

--编辑--

我想我会在此处添加该构造函数,以展示如何确保调用 new DrivePacket(path,size)(无 ID)的“旧”代码能够正常工作:

public record DrivePacket(Path drivePath,String id) {
    public DrivePacket(Path drivePath,long driveSize) {
        this(drivePath,driveSize,"");
    }
}

'full' all-3-of-em 构造函数存在,这定义了第二个构造函数,确保任何只执行 new DrivePacket(path,size) 的代码获得 {{1} 的 ID }}。所有 DrivePacket 都有一个 ID(你不能让一半有它而另一半没有;那么“DrivePacket”将不再描述单一类型概念,而不是 java 的工作原理),现在旧式 DrivePacket 对象有一个ID 的空字符串。

,

可以兼容添加一个组件到记录中,如果有一个合理的默认值,这是在设计这个特性时考虑的。考虑:

record Point(int x,int y) { }

并且您想添加一个 z 组件,其中零是合理的默认值。如果你只是一味地改成

record Point(int x,int y,int z) { }

这不会与现有客户端的源代码或二进制文件兼容,但您可以通过为旧状态描述提供替代构造函数来解决此问题:

record Point(int x,int z) { 
    public Point(int x,int y) { this(x,y,0); }
}

现在,旧的构造函数调用(二进制和源代码)和旧的序列化实例(如果默认值是相同的零默认值,序列化将用于序列化流中不存在的字段)将按预期工作。但是,它与renamereorderremove 组件不兼容。