(Item 10) Override clone() judiciously

 

(Item 10) Override clone() judiciously

General Contract

x.clone() != x

x.clone().getClass() == x.getClass()

x.clone().equal(x) == true

 

In practice, a class that implements Cloneable is expected to provide a properly functioning public method.

 

1) If every field contains a primitive value or a reference to an immutable object

public Object clone() {

        try {

                return super.clone();

        } catch(CloneNotSupportedException e) {

                throw new Error("Assertion failure"); // Can't happen

        }

}

 

2) If, however, your object contains fields that refer to mutable objects

public class Stack {

        private Object[] elements;

        private int size = 0;

 

        public Stack(int initialCapacity) {

                this.elements = new Object[initialCapacity];

        }

 

        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;

        }

 

        // Ensure space for at least one more element.

        private void ensureCapacity() {

           if (elements.length == size) {

                   Object oldElements[] = elements;

                   elements = new Object[2 * elements.length + 1];

                   System.arraycopy(oldElements, 0, elements, 0, size);

           }

        }

}

//In effect, the clone method functions as another constructor; you must ensure that it does no harm to

//the original object and that it properly establishes invariants on the clone

public Object clone() throws CloneNotSupportedException {

    Stack result = (Stack) super.clone();

    result.elements = (Object[]) elements.clone();

    return result;

}

 

3) It is not always sufficient to call clone() recursively

suppose you are writing a clone method for a hash table whose internals consist of an array of buckets,

each of which references the first entry in a linked list of key-value pairs or is null if the bucket is empty

 

public class HashTable implements Cloneable {

    private Entry[] buckets = ...;

 

    private static class Entry {

        Object key;

        Object value;

        Entry  next;

 

        Entry(Object key, Object value, Entry next) {

            this.key   = key;

            this.value = value;

            this.next  = next; 

        }

// Recursively copy the linked list headed by this Entry

        Entry deepCopy() {

            return new Entry(key, value,

                next == null ? null : next.deepCopy());

        }

   }

 

   public Object clone() throws CloneNotSupportedException {

       HashTable result = (HashTable) super.clone();

       result.buckets = new Entry[buckets.length];

       for (int i = 0; i < buckets.length; i++)

           if (buckets[i] != null)

               result.buckets[i] = (Entry)

                  buckets[i].deepCopy();

 

       return result;

   }

   ... // Remainder omitted

}

 

Use clone as little as possible, try to use copy constructor/static factory instead of clone()

For example: java.util.ArrayList contains a copy constructor : ArrayList(Collection c)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值