Copy an object in Java

后端 未结 7 583
伪装坚强ぢ
伪装坚强ぢ 2020-12-09 03:41

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.

I assumed that I needed t

7条回答
  •  长情又很酷
    2020-12-09 04:21

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

    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 result is only a shallow copy, meaning that if there's a reference to an object, both the original and result will share the same object. For example, if C contains private int[] data you'd probably want to copy that.

    ...
    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. clone is 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.

    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.

提交回复
热议问题