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

JDK 16 Records, Constructors and Additions Over Time?

我对使用新的 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;
        }
}

记录是只针对没有任何可变性的对象,还是可以随着时间的推移而延长?

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

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

遇到这种情况怎么办?我可以向构造函数添加选项并将它们存储在私有最终字段中吗?或者我应该做一个 DrivePacket -> RemoteDrivePacket 的子 class,还是应该为 RemoteDrivePacket 做一个标记界面?

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

它们不能被子类化,它们不能有'adding one separately'意义上的字段,但你可以简单地在其中扔一个新的属性; public record DrivePacket(Path drivePath, long driveSize, String id) {} 工作正常。

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

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

--编辑--

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

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

'full' all-3-of-em 构造函数 存在,这定义了第二个构造函数,确保任何代码 new DrivePacket(path, size)获得 "" 的 ID。所有 DrivePackets 都有一个 ID(你不能让一半有它而另一半没有;那么 'DrivePacket' 将不再描述单一类型的概念,而不是 java 的工作方式),现在已经过时了-style DrivePacket 对象的 ID 为空字符串。

如果有合理的默认值,可以兼容地添加一个组件到记录中,并且在设计此功能时考虑到了这一点。考虑:

record Point(int x, int y) { }

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

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

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

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

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