可以复制记录吗?

我在谷歌上找不到任何关于记录使用的材料。Cloneable

我在想这样的事情:

record Foo() implements Cloneable {
    public Foo clone() {...}
}

这是一件好事吗?我们应该避免它以支持未来的枯萎吗?

回答

除了基本问题之外,Cloneable还有另一个重要的原因为什么不应该进行记录Cloneable

记录本质上是不可变的。不可变类的最大优点之一是可以不用担心对象身份:任何两个具有相同值的对象都可以完全互换使用。JavaDoc 有一个称为基于值的类的概念,它更进一步(通过禁止公共构造函数并使任何显式使用对象标识成为错误),但确实很好地描述了基本思想。

因此,创建一个clone()记录只会产生第二个对象,该对象的所有意图和目的都应该与原始对象完全相同,并且永远不会改变为不同的行为(因为记录是不可变的)。

这表明,没有正当理由clone()Record

并且只是为了完整起见:可以(但同样不建议)Cloneable在记录中实施:

record Foo(String a) implements Cloneable {
  public Foo clone() {
    try {
      return (Foo) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException("this can't happen", e);
    }
  }
}

运行此测试代码证明确实创建了一个克隆:

Foo original = new Foo("bar");
Foo clonedFoo = original.clone();
System.out.println(original + " / " + clonedFoo);
System.out.println(System.identityHashCode(original) + " / " + System.identityHashCode(clonedFoo));

产生这个输出:

record Foo(String a) implements Cloneable {
  public Foo clone() {
    try {
      return (Foo) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException("this can't happen", e);
    }
  }
}

  • I think you're (dangerously) confusing records (which are a language feature about classes whose API and representation are transparently related) and primitive classes (nee value types). "Value-based classes" are entirely about classes that are intended to have value semantics; records do not necessarily.
  • The claim made here that records have no use at all for `clone()` is overblown. There are all the usual reasons that `clone()` is problematic, but records neither add nor subtract from these.
  • @JoachimSauer Full agreement with all of that -- yes immutability is the primary case, and many of the other cases should give users cause to more deeply explore what they're trying to achieve. But the OP asked if there was any reason a record _cannot_ implement `Clonable`. And the simple answer is, the two concepts are compatible, even if the intersection is small. So by all means, say "you can, but it's risky, and you're probably doing something questionable, are you sure you want that?" And perhaps: "LIke with every other class besides arrays, prefer a copy constructor."
  • @JoachimSauer and Holger: The reason I'm pushing back here is not that I'm some sort of secret fan of `Clonable`; it's that I'm a rabid anti-fan of making things more complicated than they are. `Clonable` sucks, but its suckage is completely independent of records. `Clonable` records suck _exactly as much_ as `Clonable` classes, no more, and no less. Let's not burden people's perceptions of records with irrelevant coupling to other features. Records are great, `Clonable` sucks, and neither affects the other. That's a simple story.
  • Yes, I've added a sample demonstrating that it *works*.
  • The claim that a clone of a record is indistinguishable from the original is still incorrect even if you ignore identity. A clone() method is free to deeply clone components, some of which might be mutable (e.g., arrays.) These are "advanced" uses of records, and might be something you would reasonably discourage in general, but they're not ruled out by the design or implementation.
  • @Holger I'm not trying to defend `Clonable`, but the OP asked if there was anything about records that was inconsistent with `Clonable`, and the answer is no. If a copy constructor does the job, it is a better choice, no question.

以上是可以复制记录吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>