Java公共克隆接口

3

创建这样的接口并在需要确保变量可克隆的地方使用它是否存在任何不好或错误的地方?

public interface PublicCloneable<I> {
    public I clone();
}

在SO上有关于Java中Cloneable接口存在问题的相关问题,我不明白为什么它不能像这样实现。

3个回答

2

您可以。创建新接口的主要问题在于,您只能在显式实现此接口的新类上使用此接口。 Java库中的现有类无法实现此接口,因为您无法更改它们的代码。(该接口不会神奇地应用于现有类型。)因此,仅当您创建一个用于所有预期使用的对象的自定义类系列并且不使用标准库类时,才有用。


1
如果你想完全使用自己的clone()实现,那应该是没问题的。但是,如果你在某些时候想要使用Object.clone(),我建议。
public interface PublicCloneable<I> extends Cloneable {
    public I clone();
}

并且在实现内部:

   public static class MyClass implements PublicCloneable<MyClass> {
     public MyClass clone() {
        try {
            return (MyClass)super.clone(); // Or do whatever you need here
        } catch (CloneNotSupportedException e) {
            // Always supported
        }
   }

我不确定它是否编译通过,但我尝试了一下,似乎没问题。

当然,结果可能因情况而异。


我在面向对象编程课上学到的方法是使用复制构造函数进行克隆,所以它总是这样的{ return new MyClass(this) }。我从未使用过Object.clone(),也不知道它是否自动执行深度复制。无论如何,我只需要接口,因为我正在创建一个泛型类,其中类型参数必须实现clone方法,以确保我可以使用它。用户需要在其类中提供正确的克隆方法。 - jmacedo
呃,java.lang.Cloneable 是关于实现而不是接口的。不要将其与实际接口类型混淆。 - Tom Hawtin - tackline
@Tom 你有权发表自己的意见,但是你当前评论的表达方式并不太合理。 - Alex Gitelman
1
@joxnas:复制构造函数的问题在于它们不支持多态性。将派生对象传递给基类的复制构造函数将创建一个新的基类类型对象,该对象无法支持派生对象的任何独特功能。例如,一个人可能会有一个ShapeBase类,它保存一个边界矩形,提供一些方法如“translate”和“scale”,并具有可重写的“Draw”方法,该方法仅绘制一个“红色X框”;其他定义的形状对象将覆盖绘制方法以绘制诸如圆形、多边形等形状。 - supercat
@joxnas:即使ShapeBase支持复制构造函数,将一个多边形传递给一个希望通过调用"new ShapeBase(passedInShape);"来复制它的例程,会创建一个BaseShape,在原始多边形的边界矩形中绘制一个红色的X。可以像处理原始多边形一样处理这个新形状,进行平移、缩放等操作,其边界框也会相应地移动,但是失去了任何关于"多边形特性"的东西。有两种解决方案:(1)让所有形状派生类支持一个受保护的克隆方法,该方法将调用本地对象的克隆方法,或者... - supercat
@joxnas: (2) 让每个形状导数实现自己的复制构造函数,并覆盖一个公共克隆方法来调用它。我更喜欢第一种方法,因为它保证新对象将与原始对象具有相同的类型,并且只需要派生类型在添加需要超出浅层复制的字段时才重写克隆方法。如果使用第二种方法,即使没有添加任何字段或添加了只需要浅层复制的字段,每个派生类型也必须重写公共克隆方法并实现复制构造函数。 - supercat

1

这很好,但是你将不得不在方法内提供自己的克隆逻辑。

java.lang.Cloneable 的想法是将一个类标记为可克隆的,并且克隆逻辑由 JVM 处理。你不能使用 Object.clone() 提供逐个字段的克隆。

你可以从 this answer 中建议的其他克隆机制中选择另一个(或与另一个接口结合使用)。


本来想提一下深度克隆。你发布的主题很不错。 - James P.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接