最近研究对象类,稍微总结一下,以后继续补充:
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); }
文章结束给大家分享下程序员的一些笑话语录:
一个合格的程序员是不会写出 诸如 “摧毁地球” 这样的程序的,他们会写一个函数叫 “摧毁行星”而把地球当一个参数传进去。