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

发布于 2024-09-15 06:26:44 字数 1245 浏览 7 评论 0原文

在代码中更容易解释,所以

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

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

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

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

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

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

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

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

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
}

???

its easier to explain in code so here

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

what can i use instead of the Object.clone() method in this example?

----------------------- extra info ------------------------------

I have added extra info but it seems to have gone in the middle of all the answers, so here it is again so it can be read.

Hi all these are all really helpful on topic of cloning or copying, which i now need to think about. but they dont help with the initial question. maybe more info from me will help you understand what im after.

I am overriding the clone for each of my objects and adding all the other clone and copy methods needed to completely clone the object, this includes adding a custom method to copy a bufferedimage.
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; 
    } 
}

but i have one variable in my class that is an Object but because it hold various other objects of different types, each of my types will have a clone method, but short of checking if its each of my types and then calling clone() on my type, which would be very long as i have many types, i cannot see how to copy or clone the object easily. is there a way os should i just write a static method like this?

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
}

???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

人│生佛魔见 2024-09-22 06:26:44

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

以下是对《Effective Java》一书作者 Josh Bloch 的采访的一些引述第二版:

如果你读过我书中有关克隆的内容,特别是如果你读到了字里行间的内容,你就会知道我认为克隆已经被彻底破坏了。有一些设计缺陷,其中最大的缺陷是 Cloneable 接口没有 clone 方法。这意味着它根本不起作用:使某些东西Cloneable不会说明您可以用它做什么。相反,它说明了它在内部可以做什么。它表示,如果重复调用 super.clone 最终会调用 Objectclone 方法,则该方法将返回原创。

但它没有说明您可以使用实现 Cloneable 接口的对象做什么,这意味着您无法执行多态 clone 操作.

以下是书中的一些引述,第 11 条:明智地覆盖克隆

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

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

public Yum(Yum yum);

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

public static Yum newInstance(Yum yum);

相关问题


替代方案:Cloneable 2.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}

所以现在给出任何 Dupable,您可以对其调用 T dup() 以获得您期望的重复副本。

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

You seem to have realized that Cloneable in Java is broken.

Here are some quotes from an interview with Josh Bloch, author of Effective Java 2nd Edition:

If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. There are a few design flaws, the biggest of which is that the Cloneable interface does not have a clone method. And that means it simply doesn't work: making something Cloneable doesn't say anything about what you can do with it. Instead, it says something about what it can do internally. It says that if by calling super.clone repeatedly it ends up calling Object's clone method, this method will return a field copy of the original.

But it doesn't say anything about what you can do with an object that implements the Cloneable interface, which means that you can't do a polymorphic clone operation.

Here are some quotes from the book, Item 11: Override clone judiciously:

[...] you are better off providing alternative means of object copying, or simply not providing the capability.

[...] A fine approach to object copying is to provide copy constructor or copy factory. A copy constructor is simply a constructor that takes a single argument whose type is the class containing the constructor:

public Yum(Yum yum);

A copy factory is the static factory analog of a copy constructor:

public static Yum newInstance(Yum yum);

Related questions


Alternative: Cloneable 2.0

If you really insist on having a Cloneable-like functionality that isn't broken, you can write something like this (generified for extra jazz):

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

The output should be something like this (as seen on ideone.com):

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

So now given any Dupable<T>, you can invoke T dup() on it to get what you expect is a duplicate copy.

This is just a proof-of-concept: in actual implementation, your copy constructor/copy factory/whatever copy mechanism will actually have the copying logic implemented, and Dupable<T> would be a public top-level interface.

知你几分 2024-09-22 06:26:44

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

The best idea is to avoid cloning, as it is broken.
Cloneable interface doesn't have method clone. Method clone is defined as protected in Object class. So to call clone you need to know the type of object to have access to clone.
Better idea is either copy constructor (as Bloch recommends) or serialization and deserialization (via XML for example).
Maybe you can gain access to clone with reflection, but I'm not sure. And I discourage it.

白馒头 2024-09-22 06:26:44

您无法确定类是否具有克隆能力,因为 clone() 是 Object 中的方法。您能做的最好的事情就是检查该类是否为 可克隆。通常,当一个类 Cloneable 时,这意味着开发人员重写了 clone() 方法。

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

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

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

您可以在此处阅读文档,以及 Josh Bloch 关于此类的声明(最后一段)。

You can't know for sure that a class has the capacity to clone because clone() is a method from Object. The best you can do is to check if the class is Cloneable. Usually when a class is Cloneable it means that the developer overrode the clone() method.

But even so, Object can't call this method.

There is the reflection solution. But as the doc says :

Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.

You can read documentation here, and there is a statement from Josh Bloch on this class (last paragraph).

各自安好 2024-09-22 06:26:44

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

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

You could check whether it implements the Cloneable interface and if it does then use the clone method.

And here is and example on how to implement it yourself.

最笨的告白 2024-09-22 06:26:44

正如其他人所说: 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()...获取所有字段,复制值到新对象。但如果对象没有无参数构造函数,这就很棘手。

As others have said: Clonable is broken and you should consider other options such as copy constructors. Having said that, here is a solution that should work if you really must use 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");
}

Or you could use reflection to clone the object field by field, if it does not implement clone()... Get all fields, copy the values to the new object. But this is tricky, if the object has no no-arg constructor.

等数载,海棠开 2024-09-22 06:26:44
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();
        }
    }
}
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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文