1

它更容易用代码解释,所以在这里

Object anObj;
anObj = new MyObj();
anObj = new Rectangle();
anObj.clone();//this doesnt exist because its on the root Object class

在此示例中,我可以使用什么来代替 Object.clone() 方法?

------------------------------------ 额外信息 ------------- -----

我已经添加了额外的信息,但它似乎已经出现在所有答案的中间,所以它再次出现,因此可以阅读。

嗨,所有这些对克隆或复制的主题都非常有帮助,我现在需要考虑一下。但他们对最初的问题没有帮助。也许我提供的更多信息将帮助您了解我所追求的。

我正在覆盖我的每个对象的克隆,并添加完全克隆对象所需的所有其他克隆和复制方法,这包括添加自定义方法来复制缓冲图像。IE:-

public Object clone() {//i copied from 'thelost's answer
    try { 
        CloningExample copy = (CloningExample)super.clone(); 
        copy.names = (LinkedList)names.clone(); 
        return copy; 
    } catch (CloneNotSupportedException e) { 
        return null; 
    } 
}

但是我的类中有一个变量是一个对象,但是因为它包含不同类型的各种其他对象,所以我的每个类型都有一个克隆方法,但是没有检查它是否是我的每个类型然后调用 clone()我的类型很长,因为我有很多类型,我看不到如何轻松复制或克隆对象。有没有办法让我只写这样的静态方法?

static findTypeAndCopy(Object thisobj){ 
    if(thisobj==null) 
        return null;

    if(thisobj instanceOf MyObj1){ 
        return ((MyObj1)thisobj).clone(); 
    }else if(thisobj instanceOf MyObj2){ 
        return ((MyObj2)thisobj).clone(); 
    ... 
    etc
}

???

4

6 回答 6

5

您似乎已经意识到Cloneable在 Java 中是坏的。

以下是对Effective Java 2nd Edition的作者Josh Bloch 的采访中的一些引述:

如果你读过我书中关于克隆的项目,尤其是如果你读到字里行间,你就会知道我认为clone它被深深地破坏了。有一些设计缺陷,其中最大的就是Cloneable接口没有clone方法。这意味着它根本行不通:做某事Cloneable并不能说明你可以用它做什么。相反,它说明了它可以在内部做什么。它说如果通过super.clone重复调用它最终调用Object'clone方法,该方法将返回原始的字段副本。

但是它没有说明你可以用实现Cloneable接口的对象做什么,这意味着你不能做多态clone操作。

以下是书中的一些引述,第 11 项:明智地覆盖clone

[...] 您最好提供对象复制的替代方法,或者干脆不提供该功能。

[...] 对象复制的一个很好的方法是提供复制构造函数复制工厂。复制构造函数只是一个构造函数,它接受一个参数,其类型是包含构造函数的类:

public Yum(Yum yum);

复制工厂是static复制构造函数的工厂模拟:

public static Yum newInstance(Yum yum);

相关问题


替代方案:Cloneable2.0

如果你真的坚持有一个Cloneable没有被破坏的类似 - 的功能,你可以写这样的东西(为额外的爵士乐而生成):

public class DupableExample {

    interface Dupable<T> {
        T dup();
    }   
    static class Sheep implements Dupable<Sheep> {
        Sheep(Sheep sheep) { }
        @Override public Sheep dup() {
            return new Sheep(this);
        }
    }
    public static void main(String[] args) {
        Dupable<?> dupable = new Sheep(null);
        System.out.println(dupable);
        System.out.println(dupable.dup());
        
        // no cast needed
        Sheep dolly2 = new Sheep(null).dup();
    }
}

输出应该是这样的(见 ideone.com):

DupableExample$Sheep@{some hexadecimal code}
DupableExample$Sheep@{a different hexadecimal code, in all likelyhood}

所以现在给定 any Dupable<T>,你可以调用T dup()它来获得你期望的副本。

这只是一个概念验证:在实际实现中,您的复制构造函数/复制工厂/任何复制机制实际上都会实现复制逻辑,并且Dupable<T>将是public顶级的interface.

于 2010-08-19T12:17:37.493 回答
4

最好的办法是避免克隆,因为它已损坏。
Cloneable接口没有方法clone。方法在类clone中定义。因此,要调用您需要知道要访问的对象的类型。更好的主意是复制构造函数(如 Bloch 建议的那样)或序列化和反序列化(例如通过 XML)。 也许您可以通过反射获得访问权限,但我不确定。我不鼓励它。protectedObjectcloneclone
clone

于 2010-08-19T12:08:00.837 回答
0

你不能确定一个类有克隆的能力,因为clone()它是 Object 的一个方法。您可以做的最好的事情是检查该类是否为Cloneable。通常,当一个类是可克隆的时,这意味着开发人员覆盖了该clone()方法。

但即便如此,Object也不能调用这个方法。

有反射解决方案。但正如医生所说:

即使以反射方式调用 clone 方法,也不能保证它会成功。

你可以在这里阅读文档,还有来自 Josh Bloch 的关于这个类的声明(最后一段)。

于 2010-08-19T11:56:12.343 回答
-1

正如其他人所说:Clonable 已损坏,您应该考虑其他选项,例如复制构造函数。话虽如此,如果您真的必须使用 clone(),这里有一个应该可以工作的解决方案:

Object clone = null;
if(anObj instanceof Clonable) {
    Method cloneMethod = anObj.getClass().getMethod("clone");
    /*
     * TODO: Handle the case where an object is cloneable but 
     * does not have a public clone() method.
     */
    clone = cloneMethod.invoke(anObj);
} else {
    throw new RuntimeException("can't clone object");
}

或者您可以使用反射逐个字段克隆对象,如果它没有实现 clone()... 获取所有字段,将值复制到新对象。但这很棘手,如果对象没有无参数构造函数。

于 2010-08-19T11:56:05.463 回答
-1

您可以检查它是否实现了Cloneable接口,如果实现了,则使用 clone 方法。

这是有关如何自己实现它的示例

于 2010-08-19T11:54:57.647 回答
-1
interface PublicCloneable extends Cloneable{
    public Object clone();
}

class MyObject implements PublicCloneable {
    public Object clone() {
        return super.clone();
    }
}

class MainObject {
    public static void main(String[] params) {
        Object m = new MyObject();

        if (m instanceof PublicCloneable) {
            Object c = m.clone();
        }
    }
}
于 2010-08-19T12:30:43.913 回答