July 17, 2017 Update

Clone method (shallow copy and deep copy) : Shallow copy and deep copy (shallow copy and deep copy) The second part I hope I can have a look at it sometime. .


Let’s learn about cloning. Fantastic chance to remember a thing! Previously, the write algorithm has been passed to confuse by ArrayList. The common scenario is an ArrayList

> result. Holds many cells: ArrayList

cell; But every time I result.add(cell); Add (new ArrayList

(cell)); result.add(new ArrayList

(cell)); That’s how it works.



Why is that? Because: In Java, any time you assign a value to an object variable using “=”, it is “reference-passed”. Only a “reference to an object” is passed. As if passing a pointer, subsequent operations are performed on the original object. Additionally, Java uses object passing as an entry parameter to default to “reference passing.”

Clone () of Object eventually calls native methods:

protected native Object clone() throws CloneNotSupportedException;
Copy the code

Native methods are generally much more efficient than non-native methods in Java. This also explains why we use the Clone () method in Object instead of first new a class and then assigning information from the original Object to the new Object, although this would also implement the clone function.

Why does a Cloneable interface have to be implemented

If overwrite the clone, you have to implements the Cloneable, otherwise it will throw CloneNotSupportedException. It’s kind of a pact.

//Object.java
    protected Object clone() throws CloneNotSupportedException {
        if(! (this instanceof Cloneable)) { throw new CloneNotSupportedException("Class " + getClass().getName() +
                                                 " doesn't implement Cloneable");
        }
        return internalClone();
    }
Copy the code

Effective Java says this is the Mixin interface. Iteye’s answer:

  1. Cloneable indicates that the interface is similar to java.io.Serializable and is used to tell the JVM that the object implements Clone. And super.clone() can return a copy.
  1. In many cases, the protected Clone method is changed to public so that others can use it.

Shallow copy and deep copy

Shallow copy: Copies the base member attributes and returns only the reference to the changed address for the reference type.


2.28 FROM API: The general intent is that, for any object x, The expression:

x.clone() ! = x x.clone().getClass() == x.getClass()Copy the code

This is also true, but not required:

       x.clone().equals(x)
Copy the code

According to convention, the returned object should be retrieved via super.clone. If a class and its superclasses(except Object) follow this convention, there is x.lone ().getClass() == x.getclass ().

Generally, in order to achieve the empirical objects to be independent, one or more fields of the object returned by super.clone need to be modified and then returned (that is, a deep copy). If a class contains only primitive fields or Immutable objects, the fields in the object returned by super.clone do not need to be modified.

FROM EFFECTIVE JAVA: If each field contains a value of a primitive type, or contains a reference to an immutable object, the returned object may be exactly what you need, in which case no further processing is required. For example, the PhoneNumber class in # 9 does exactly that:

public final class PhoneNumber { private final short areaCode; private final short prefix; private final short lineNumber; public PhoneNumber(int areaCode, int prefix, int lineNumber) { this.areaCode = (short) areaCode; this.prefix = (short) prefix; this.lineNumber = (short) lineNumber; }}Copy the code

Then you just need to:

@Override
public PhoneNumber clone() {
    try {
        return(PhoneNumber) super.clone(); } catch(CloneNotSupportedException e) { throw new AssertionError(); }}Copy the code

The clone method returns PhoneNumber instead of Object. This has been legal since the Java1.5 release, which introduced convariant return types as generics. It’s a rule: never ask a customer to do anything that a class library can do for them.

It is not possible to return super.clone directly for a class that has the correct values in the size field, but whose elements field references the same array as the original Stack instance.

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    publci Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (0 == size) throw new EmptyStackException();
        return elements[--size];
    }

    /**
     * Ensure space for at least one more element
     * roughly doubling the capacity each time the 
     * array needs to grow
     * /
    private void ensureCapacity() {
        if(size == elements.length) elements = Arrays.copyOf(elements, 2* size + 1); }}Copy the code

At this point, deep copy is needed, and you can recurse:

@Override
public Stack clone() {
    try {
        Stack result = (Stack) super.clone();
        result.elements = elements.clone();
        returnresult; } catch (CloneNotSupportedException e) { throw new AssertionError(); }}Copy the code

Or bucket clone:

@Override
public HashTable clone() {
    try {
        HashTable result = (HashTable) super.clone();
        result.buckets = buckets.clone();
        returnresult; } catch (CloneNotSupportedException e) { throw new AssertionError(); }}Copy the code

I won’t go into details here. It’s a little complicated. Let’s read a book.

. In short, deep copy is cumbersome. The book says it’s best not to overwrite and rarely to call (because it’s perfectly possible to create a new one). I’m not going to dig too deeply here.


See also: http://blog.csdn.net/Jing_Unique_Da/article/details/49901933 http://lovelace.iteye.com/blog/182772 http://www.cnblogs.com/tonyluis/p/5778266.html http://www.oschina.net/translate/java-copy-shallow-vs-deep-in-which-you-will-swim https://zhidao.baidu.com/question/546603399.html