Cloneable interface

147 阅读1分钟

If you must implement cloneable interface, please rewrite the clone method correctly.

public class HashTable implements Cloneable {

    private Entry[] buckets = null;

    private static class Entry {
        final Object key;
        Object value;
        Entry next;

        public Entry(Object key, Object value, Entry next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        // This method will cause stack overflow if the list is too long.
//        Entry deepCopy() {
//            return new Entry(key, value,
//                    next == null ? null : next.deepCopy());
//        }

        // Iteratively copy the linked list headed by this Entry
        Entry deepCopy() {
            Entry result = new Entry(key, value, next);
            for (Entry p = result; p.next != null; p = p.next) {
                p.next = new Entry(p.next.key, p.next.value, p.next.next);
            }
            return result;
        }
    }

    @Override
    public HashTable clone() {
        try {
            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] = buckets[i].deepCopy();
                }
                return result;
            }
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
        return null;
    }
}

Usually, the copy function is provided by the constructor or factory. A notable exception to this rule is the array, which is easily copied using the clone method.