对象类Effective Java:Ch3_Methods:Item11_谨慎重写clone()

最近研究对象类,稍微总结一下,以后继续补充:

    Cloneable口接的的目是作为对象的一个mixin口接,标明对象答应克隆;但这个的目没有到达。

    其主要点缺是,Cloneable缺乏一个clone()方法,而Object.clone()是受护保的。

    

    平日,实现口接是为了标明类可为以它的客户做些什么;而Cloneable倒是改变了超类中受护保方法的行为。

    

    Object.clone()定义的定约:

/**
建创并返回此对象的一个副本。“副本”的确准义含可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式: 
x.clone() != x
是准确的,则表达式: 
x.clone().getClass() == x.getClass()将为 true,
但这些不是绝对条件。一般情况下是: 
x.clone().equals(x)将为 true,但这不是绝对条件。 

--按照例惯,返回的对象该应通过用调 super.clone 取得。
如果一个类及其全部的超类(Object 除外)都遵照此定约,则 x.clone().getClass() == x.getClass()。 


--按照例惯,此方法返回的对象该应独立于该对象(正被克隆的对象)。
要取得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段停止修改。
这平日意味着要复制包括正在被克隆对象的外部“深层结构”的全部可变对象,并用使对副本的用引替换对这些对象的用引。
如果一个类只包括基本字段或对稳定对象的用引,那么平日不要需修改 super.clone 返回的对象中的字段。 


Object 类的 clone 方法行执特定的克隆作操。
首先,如果此对象的类不能实现口接 Cloneable,则会抛出 CloneNotSupportedException。
注意:全部的组数都被视为实现口接 Cloneable。

否则,此方法会建创此对象的类的一个新例实,并像通过分配那样,严厉用使此对象应相字段的内容初始化该对象的全部字段;
这些字段的内容没有被自我克隆。所以,此方法行执的是该对象的“浅表复制”,而不“深层复制”作操。 

Object 类本身不实现口接 Cloneable,所以在类为 Object 的对象上用调 clone 方法将会致导在运行时抛出异常。 
*/

protected native Object clone() throws CloneNotSupportedException;

 

    

    

    全部实现了Cloneable口接的类,都该应供给一个public的clone()方法;

    在这个clone()方法中,首先用调super.clone(),然后正修任何要需正修的域。

    例如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(); // --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;    // --递归用调例实变量.clone()
	    }
	    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()时,如果该变量为final,则不行!

    

    clone构架与饮用可变对象的final域的常正用法是不兼容的!

    

    

    

    另一个实现对象拷贝的好办法是供给一个拷贝构造器(copy constructor)或者拷贝工厂(copy factory)。

    例如:

public Yum(Yum yum);
public static Yum newInstance(Yum yum);

    这类方法比clone有更多优势:

    

  • 不依赖于某一种有风险的、语言外之的对象建创机制
  • 不要求遵照还没有定制好档文的标准
  • 不会与final域的常正用使发生冲突
  • 不会抛出不必要的受检异常
  • 不要需停止类型转换

    另外,拷贝构造器和拷贝工厂可以带数参,数参类型一般是该类实现的口接,以便用户择选拷贝的实现类型。

    例如,有一个HashSet s,望希把它拷贝成一个TreeSet,可以用调:new TreeSet(s)

/**
     * Constructs a new tree set containing the elements in the specified
     * collection, sorted according to the <i>natural ordering</i> of its
     * elements.  All elements inserted into the set must implement the
     * {@link Comparable} interface.  Furthermore, all such elements must be
     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
     * {@code ClassCastException} for any elements {@code e1} and
     * {@code e2} in the set.
     *
     * @param c collection whose elements will comprise the new set
     * @throws ClassCastException if the elements in {@code c} are
     *         not {@link Comparable}, or are not mutually comparable
     * @throws NullPointerException if the specified collection is null
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    

    

    

    

    

    

    

    

文章结束给大家分享下程序员的一些笑话语录: 一个合格的程序员是不会写出 诸如 “摧毁地球” 这样的程序的,他们会写一个函数叫 “摧毁行星”而把地球当一个参数传进去。

posted @ 2013-05-09 19:52  xinyuyuanm  阅读(197)  评论(0编辑  收藏  举报