如何克隆一个你不知道类型的对象?

时间:2010-08-19 11:51:43

标签: java object cloning

在代码中更容易解释所以

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

在这个例子中我可以使用什么代替Object.clone()方法?

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

我已经添加了额外的信息,但它似乎已经在所有答案的中间,所以在这里它又是如此,它可以被阅读。

大家都非常有帮助克隆或复制这个主题,我现在需要考虑一下。但他们对最初的问题没有帮助。也许更多来自我的信息将帮助您了解后续的内容。

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

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; 
    } 
}

但是我的类中有一个变量是Object,但是因为它包含不同类型的各种其他对象,我的每个类型都会有一个克隆方法,但是不能检查我的每个类型是否然后调用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
}

???

6 个答案:

答案 0 :(得分:4)

最好的办法是避免克隆,如it is broken.
Cloneable接口没有方法clone。方法cloneprotected类中定义为Object。因此,要调用clone,您需要知道有权访问clone的对象类型。 更好的想法是复制构造函数(如Bloch推荐)或序列化和反序列化(例如通过XML) 也许你可以通过反思访问clone,但我不确定。我劝阻它。

答案 1 :(得分:4)

您似乎已经意识到Java中的Cloneable已被破坏。

以下是 Effective Java 2nd Edition 的作者an interview with Josh Bloch的一些引用:

  

如果您已经阅读了我的书中有关克隆的内容,特别是如果您在这些内容之间进行了阅读,您会发现我认为clone已经被彻底打破了。存在一些设计缺陷,其中最大的缺点是Cloneable接口没有clone方法。这意味着它根本不起作用:制作一些Cloneable并没有说明你可以用它做什么。相反,它说明了内部可以做些什么。它表示如果反复调用super.clone,最终会调用Object的{​​{1}}方法,此方法将返回原始字段的字段副本。

     

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

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

  

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

     

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

clone
     

复制工厂是复制构造函数的public Yum(Yum yum); 工厂模拟:

static

相关问题


替代方案:public static Yum newInstance(Yum yum); 2.0

如果你真的坚持使用Cloneable这样的功能没有被打破,你可以写下这样的东西(为额外的爵士乐做好准备):

Cloneable

输出应该是这样的(as seen on ideone.com):

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();
    }
}

现在给予任何DupableExample$Sheep@{some hexadecimal code} DupableExample$Sheep@{a different hexadecimal code, in all likelyhood} ,您可以在其上调用Dupable<T>以获得您期望的副本。

这只是一个概念验证:在实际实现中,您的复制构造函数/复制工厂/任何复制机制实际上都会实现复制逻辑,而T dup()将是Dupable<T>顶部-level public

答案 2 :(得分:0)

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

但即便如此,Object也无法调用此方法。

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

  

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

您可以阅读文档here,而there是Josh Bloch关于此课程的声明(最后一段)。

答案 3 :(得分:-1)

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

here就是如何自己实现它的例子。

答案 4 :(得分:-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()...获取所有字段,将值复制到新对象。但是如果对象没有no-arg构造函数,这很棘手。

答案 5 :(得分:-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();
        }
    }
}