国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Effective Java

2019-11-14 22:26:21
字體:
來源:轉載
供稿:網友
Effective java - 謹慎覆蓋clone

覆蓋clone時需要實現Cloneable接口,Cloneable并沒有定義任何方法。那Cloneable的意義是什么?如果一個類實現了Clonable,Object的clone方法就可以返回該對象的逐域拷貝,否則會拋出CloneNotSupportedException

通常,實現接口是為了表明類的行為。而Cloneable接口改變了超類中PRotected方法的行為。這是種非典型用法,不值得仿效。

好了,既然覆蓋了clone方法,我們需要遵守一些約定:

  • x.clone() != x;
  • x.clone().getClass() = x.getClass();
  • x.clone().equals(x);

另外,我們必須保證clone結果不能影響原始對象的同時保證clone方法的約定。

比如下面這種情況,沒有覆蓋clone方法,直接得到super.clone()的結果:

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);    }}

結果可想而知,clone結果的elements和原始對象的elements引用同一個數組。

既然如此,覆蓋clone方法,并保證不會傷害到原始對象:

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

雖然把elements單獨拿出來clone了一遍,但這種做法的前提是elements不是final。其實再正常不過,clone無法和引用可變對象的不可變field兼容。

如果數組的元素是引用類型,當某個元素發生改變時仍然會出現問題。此處以Hashtable為例,Hashtable中的元素用其內部類Entry。

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;    }    //..}

如果像Stack例子中那樣直接對elements進行clone,某個Entry發生變化時clone出來的Hashtable也隨之發生變化。

于是Hashtable中如此覆蓋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();    }}

鑒于clone會導致諸多問題,有兩點建議:

  • 不要擴展Cloneable接口
  • 為繼承而設計的類不要實現Cloneable接口

上一篇:JDBC的總結

下一篇:Effective Java

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西林县| 类乌齐县| 屏东市| 南安市| 百色市| 潼关县| 嘉善县| 尚志市| 内江市| 日土县| 玉田县| 林西县| 罗城| 绿春县| 临湘市| 海安县| 阿瓦提县| 麦盖提县| 河南省| 布尔津县| 长白| 永定县| 奇台县| 常州市| 石屏县| 贵港市| 西林县| 芜湖县| 高安市| 土默特右旗| 平乡县| 盐津县| 兴国县| 象山县| 边坝县| 锡林郭勒盟| 宜良县| 门源| 晴隆县| 文山县| 松溪县|