在 Java 中复制对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/475842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:07:42  来源:igfitidea点击:

Copy an object in Java

javaobjectcopyclone

提问by Tray

I have an object that I need to copy in Java. I need to create a copy and run some tests on it without changing the original object itself.

我有一个需要在 Java 中复制的对象。我需要创建一个副本并对其运行一些测试,而无需更改原始对象本身。

I assumed that I needed to use the clone() method, but this is protected. Having done some research on the net, I can see that this can be overriden with a public method in my class. But I cannot find an explanation on how to do this. How could this be done?

我假设我需要使用 clone() 方法,但这是受保护的。在网上做了一些研究后,我可以看到这可以用我班上的公共方法覆盖。但我找不到关于如何做到这一点的解释。这怎么可能?

Also, is this the best way of achieving what I need?

另外,这是实现我需要的最佳方式吗?

回答by Yoni Roit

Some options:

一些选项:

  • You can implement Cloneablefor your object and put clone()method as public. See full explanation here: http://www.cafeaulait.org/course/week4/46.html
    However, this produces a shallow copy and might be not something you want.
  • You can serialize and deserialize your object. You will need to implement Serializableinterface for the object and all its fields.
  • You can use XStreamto perform serialization via XML - you won't have to implement anything here.
  • 您可以Cloneable为您的对象实现并将clone()方法设为公共。请参阅此处的完整解释:http: //www.cafeaulait.org/course/week4/46.html
    但是,这会生成一个浅表副本,可能不是您想要的。
  • 您可以序列化和反序列化您的对象。您将需要Serializable为对象及其所有字段实现接口。
  • 您可以使用XStream通过 XML 执行序列化 - 您不必在此处实现任何内容。

回答by Gareth Davis

For test code Serialization is maybe the safest answer, especially if the object is already Serializable try Apache Commons SerializationUtils for an implementation.

对于测试代码,序列化可能是最安全的答案,特别是如果对象已经是可序列化的,请尝试使用 Apache Commons SerializationUtils 进行实现。

回答by ecleel

Another option by using Copy Constructor (from Java Practices):

使用 Copy Constructor 的另一种选择(来自Java Practices):

public final class Galaxy {

    public Galaxy (double aMass, String aName) {
        fMass = aMass;
        fName = aName;
    }

    /**
    * Copy constructor.
    */
    public Galaxy(Galaxy aGalaxy) {
        this(aGalaxy.getMass(), aGalaxy.getName());
        //no defensive copies are created here, since 
        //there are no mutable object fields (String is immutable)
    }

    /**
    * Alternative style for a copy constructor, using a static newInstance
    * method.
    */
    public static Galaxy newInstance(Galaxy aGalaxy) {
        return new Galaxy(aGalaxy.getMass(), aGalaxy.getName());
    }

    public double getMass() {
        return fMass;
    }

    /**
    * This is the only method which changes the state of a Galaxy
    * object. If this method were removed, then a copy constructor
    * would not be provided either, since immutable objects do not
    * need a copy constructor.
    */
    public void setMass( double aMass ){
        fMass = aMass;
    }

    public String getName() {
        return fName;
    }

    // PRIVATE /////
    private double fMass;
    private final String fName;

    /**
    * Test harness.
    */
    public static void main (String... aArguments){
        Galaxy m101 = new Galaxy(15.0, "M101");

        Galaxy m101CopyOne = new Galaxy(m101);
        m101CopyOne.setMass(25.0);
        System.out.println("M101 mass: " + m101.getMass());
        System.out.println("M101Copy mass: " + m101CopyOne.getMass());

        Galaxy m101CopyTwo = Galaxy.newInstance(m101);
        m101CopyTwo.setMass(35.0);
        System.out.println("M101 mass: " + m101.getMass());
        System.out.println("M101CopyTwo mass: " + m101CopyTwo.getMass());
    }
} 

回答by Brian Agnew

Joshua Bloch has some interesting things to say about cloneable. Depending on the size/construction of the object, I'd add a copy constructor to the object, or serialise/deserialise using one of the solutions mentioned above.

Joshua Bloch关于 cloneable一些有趣的事情要说。根据对象的大小/构造,我会向对象添加复制构造函数,或者使用上述解决方案之一进行序列化/反序列化。

回答by Ronald Blaschke

There are two popular approaches. One is to provide a clonemethod as you mentioned, like so.

有两种流行的方法。一个是提供clone你提到的方法,就像这样。

public class C implements Cloneable {
    @Override public C clone() {
        try {
            final C result = (C) super.clone();
            // copy fields that need to be copied here!
            return result;
        } catch (final CloneNotSupportedException ex) {
            throw new AssertionError();
        }
}

Pay attention to the "copy fields ... here!" part. The initial resultis only a shallow copy, meaning that if there's a reference to an object, both the original and resultwill share the same object. For example, if Ccontains private int[] datayou'd probably want to copy that.

注意“复制字段......在这里!” 部分。最初result的只是一个浅拷贝,这意味着如果有一个对象的引用,原始的和result将共享同一个对象。例如,如果C包含private int[] data您可能想要复制它。

...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...

Note that you don't need to copy primitive fields, as their content is already copied, or immutable objects, as they can't change anyways.

请注意,您不需要复制原始字段,因为它们的内容已经被复制,或者不可变对象,因为它们无论如何都无法更改。

The second approach is to provide a copy constructor.

第二种方法是提供一个复制构造函数。

public class C {
    public C(final C c) {
        // initialize this with c
    }
}

Or a copy factory.

或者复印厂。

public class C {
    public static C newInstance(final C c) {
        return new C(c);
    }

    private C(final C c) {
        // initialize this with c
    }
}

Both approaches have their respective properties. cloneis nice because its a method, so you don't have to know the exact type. In the end, you should always end up with a "perfect" copy. The copy constructor is nice because the caller has a chance to decide, as can be seen by the Java Collections.

两种方法都有其各自的特性。 clone很好,因为它是一种方法,因此您不必知道确切的类型。最后,你应该总是得到一个“完美”的副本。复制构造函数很好,因为调用者有机会做出决定,这可以从 Java 集合中看出。

final List c = ... 
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?

final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties

I recommend choosing either approach, whichever suits you better.

我建议选择任何一种方法,哪种方法更适合您。

I'd use the other approaches, like reflective copying or immediate serializing/deserializing, in unit tests only. To me, they feel less appropriate for production code, mainly because of performance concerns.

我只会在单元测试中使用其他方法,例如反射复制或立即序列化/反序列化。对我来说,它们不太适合生产代码,主要是因为性能问题。

回答by Chandra Sekhar

There are multiple ways to copy object in java(shallow or deep).
This Answerwill help you.

java中有多种复制对象的方法(浅或深)。
这个答案会帮助你。

回答by A.G

You can use org.apache.commons.lang3.SerializationUtils class for object cloning, - Class should implement Serializable interface.

您可以使用 org.apache.commons.lang3.SerializationUtils 类进行对象克隆, - 类应实现 Serializable 接口。

  • ClassName copyobject = SerializationUtils.clone(classobjectTocopy)
  • ClassName copyobject = SerializationUtils.clone(classobjectTocopy)

SerializationUtils.clone is also supported on Google App Engine instance

Google App Engine 实例也支持 SerializationUtils.clone