Effective Java-Carefully overwrite clone

Source: Internet
Author: User

You need to implement the Cloneable interface when overriding clone, Cloneable does not define any methods.
What is the meaning of that cloneable?
If a class implements the Clonable,object clone method, it can return a domain-wise copy of the object, otherwise it will throw clonenotsupportedexception.


Typically, an interface is implemented to indicate the behavior of a class.
The Cloneable interface changes the behavior of the protected method in the superclass.
This is an atypical usage and is not worthy of imitation.


Well, since we've covered the Clone method, we need to follow some conventions:

    • X.clone ()! = x;
    • X.clone (). GetClass () = X.getclass ();
    • X.clone (). equals (x);

In addition, we must ensure that the clone result does not affect the original object while guaranteeing the Clone method's contract.


For example, in the following case, there is no overwrite clone method, directly get Super.clone () Result:

import java.util.Arrays;public class Stack implements Cloneable {    private Object[] elements;    private int size = 0;    private static final int DEFAULT_INITIAL_CAPACITY = 16;    public Stack() {        this.elements = new Object[DEFAULT_INITIAL_CAPACITY];    }    public void push(Object e) {        ensureCapacity();        elements[size++] = e;    }    public Object pop() {        if (size == 0)            throw new EmptyStackException();        Object result = elements[--size];        elements[size] = null; // Eliminate obsolete reference        return result;    }    public boolean isEmpty() {        return size == 0;    }    // Ensure space for at least one more element.    private void ensureCapacity() {        if (elements.length == size)            elements = Arrays.copyOf(elements, 2 * size + 1);    }}


As a result, the elements of the clone result and the elements of the original object refer to the same array.

In this case, overwrite the Clone method and ensure that the original object is not harmed:

@Overridepublic Stack clone() {    try {        Stack result = (Stack) super.clone();        result.elements = elements.clone();        return result;    } catch (CloneNotSupportedException e) {        throw new AssertionError();    }}

Although the elements was taken out of the clone once, but the premise of this approach is that elements is not final.
It's normal. However, clone cannot be compatible with immutable field referencing mutable objects.


If an element of an array is a reference type, the problem still occurs when an element changes.
Here, for example Hashtable, the elements in Hashtable are entry with their inner classes.

private static class Entry<K,V> implements Map.Entry<K,V> {    int hash;    final K key;    V value;    Entry<K,V> next;    protected Entry(int hash, K key, V value, Entry<K,V> next) {        this.hash = hash;        this.key =  key;        this.value = value;        this.next = next;    }    //..}


If you clone the elements directly as in the stack example, the hashtable of the clone will change when a entry changes.

So the hashtable is so covered with clone:

/** * Creates a shallow copy of this hashtable. All the structure of the * hashtable itself is copied, but the keys and values are not cloned. * This is a relatively expensive operation. * * @return  a clone of the hashtable */public synchronized Object clone() {    try {        Hashtable<K,V> t = (Hashtable<K,V>) super.clone();        t.table = new Entry[table.length];        for (int i = table.length ; i-- > 0 ; ) {            t.table[i] = (table[i] != null)                ? (Entry<K,V>) table[i].clone() : null;        }        t.keySet = null;        t.entrySet = null;        t.values = null;        t.modCount = 0;        return t;    } catch (CloneNotSupportedException e) {        // this shouldn‘t happen, since we are Cloneable        throw new InternalError();    }}


Since clone can cause many problems, there are two suggestions:

    • Do not extend the Cloneable interface
    • Classes designed for inheritance do not implement the Cloneable interface

Effective Java-Overwrite clone with care

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.