首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中复制对象

在Java中复制对象
EN

Stack Overflow用户
提问于 2009-01-24 10:40:47
回答 5查看 73.8K关注 0票数 21

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

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

另外,这是实现我所需的最好方法吗?

EN

回答 5

Stack Overflow用户

发布于 2009-01-24 11:07:22

另一种选择是使用复制构造函数(从Java Practices):

代码语言:javascript
复制
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());
    }
} 
票数 30
EN

Stack Overflow用户

发布于 2009-01-24 16:12:56

有两种流行的方法。一种是提供您提到的clone方法,如下所示。

代码语言:javascript
复制
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();
        }
}

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

代码语言:javascript
复制
...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...

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

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

代码语言:javascript
复制
public class C {
    public C(final C c) {
        // initialize this with c
    }
}

或者是一个复制品工厂。

代码语言:javascript
复制
public class C {
    public static C newInstance(final C c) {
        return new C(c);
    }

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

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

代码语言:javascript
复制
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

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

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

票数 21
EN

Stack Overflow用户

发布于 2009-01-24 11:04:04

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

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/475842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档