1. 程式人生 > >第10條:謹慎地改寫clone

第10條:謹慎地改寫clone

/**
 * A class implements the <code>Cloneable</code> interface to 
 * indicate to the {@link java.lang.Object#clone()} method that it 
 * is legal for that method to make a 
 * field-for-field copy of instances of that class. 
 * <p>
 * Invoking Object's clone method on an instance that does not implement the 
 * <code>Cloneable</code> interface results in the exception 
 * <code>CloneNotSupportedException</code> being thrown.
 * <p>
 * By convention, classes that implement this interface should override 
 * <tt>Object.clone</tt> (which is protected) with a public method.
 * See {@link java.lang.Object#clone()} for details on overriding this
 * method.
 * <p>
 * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
 * Therefore, it is not possible to clone an object merely by virtue of the
 * fact that it implements this interface.  Even if the clone method is invoked
 * reflectively, there is no guarantee that it will succeed.
 *
 * @author  unascribed
 * @version 1.17, 11/17/05
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0
 */
public interface Cloneable { 
}


介面如上,但是裡面卻沒有任何方法。

在Object類裡,有clone方法:

    /**
     * Creates and returns a copy of this object.  The precise meaning 
     * of "copy" may depend on the class of the object. The general 
     * intent is that, for any object <tt>x</tt>, the expression:
     * <blockquote>
     * <pre>
     * x.clone() != x</pre></blockquote>
     * will be true, and that the expression:
     * <blockquote>
     * <pre>
     * x.clone().getClass() == x.getClass()</pre></blockquote>
     * will be <tt>true</tt>, but these are not absolute requirements. 
     * While it is typically the case that:
     * <blockquote>
     * <pre>
     * x.clone().equals(x)</pre></blockquote>
     * will be <tt>true</tt>, this is not an absolute requirement. 
     * <p>
     * By convention, the returned object should be obtained by calling
     * <tt>super.clone</tt>.  If a class and all of its superclasses (except
     * <tt>Object</tt>) obey this convention, it will be the case that
     * <tt>x.clone().getClass() == x.getClass()</tt>.
     * <p>
     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * it may be necessary to modify one or more fields of the object returned
     * by <tt>super.clone</tt> before returning it.  Typically, this means
     * copying any mutable objects that comprise the internal "deep structure"
     * of the object being cloned and replacing the references to these
     * objects with references to the copies.  If a class contains only
     * primitive fields or references to immutable objects, then it is usually
     * the case that no fields in the object returned by <tt>super.clone</tt>
     * need to be modified.
     * <p>
     * The method <tt>clone</tt> for class <tt>Object</tt> performs a 
     * specific cloning operation. First, if the class of this object does 
     * not implement the interface <tt>Cloneable</tt>, then a 
     * <tt>CloneNotSupportedException</tt> is thrown. Note that all arrays 
     * are considered to implement the interface <tt>Cloneable</tt>. 
     * Otherwise, this method creates a new instance of the class of this 
     * object and initializes all its fields with exactly the contents of 
     * the corresponding fields of this object, as if by assignment; the
     * contents of the fields are not themselves cloned. Thus, this method 
     * performs a "shallow copy" of this object, not a "deep copy" operation.
     * <p>
     * The class <tt>Object</tt> does not itself implement the interface 
     * <tt>Cloneable</tt>, so calling the <tt>clone</tt> method on an object 
     * whose class is <tt>Object</tt> will result in throwing an
     * exception at run time.
     *
     * @return     a clone of this instance.
     * @exception  CloneNotSupportedException  if the object's class does not
     *               support the <code>Cloneable</code> interface. Subclasses
     *               that override the <code>clone</code> method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    protected native Object clone() throws CloneNotSupportedException;


當一個類實現Cloneable介面時,預設是不會重寫clone方法的,在eclipse新建類C:

public class C implements Cloneable {

}


所以,要主動去重寫clone方法,並且把clone方法設定為public,在方法內部,還要呼叫super.clone()

public class C implements Cloneable {

	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	
}


這樣,就可以了。

clone方法是另一個構造方法,必須確保它不會傷害到原始物件,也就是說,要進行深clone。如果是淺clone,那麼clone出來的,只是原始物件的引用。

為了使得類是一個可克隆的,類裡的某些域,不能是final的,否則就無法賦值了。

介面有很多缺點,所以有些專家級的程式設計師,從來不去重寫clone方法。可以用一種拷貝構造方法來代替clone():

public class C {
	private String name = null;
	
	public C(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

	public C(C c) {
		this.name = new String(c.getName());
	}
	
	public static void main(String[] args) {
		C c1 = new C("C");
		C c2 = new C(c1);
		System.out.println(c1 + ":" + c1.getName());
		System.out.println(c2 + ":" + c2.getName());
	}
}


上面的

	public C(C c) {
		this.name = new String(c.getName());
	}


就是拷貝構造方法,或者用靜態工廠方法public static C newInstance()來代替。

相關推薦

10謹慎改寫clone

/** * A class implements the <code>Cloneable</code> interface to * indicate to the {@link java.lang.Object#clone()} method

10謹慎改寫clone

    原作者在這一條上用了8頁的篇幅,翻譯版也有7頁,足以說明這一條的重要性。我個人對此條的標註是重量級的5顆星!     克隆——是一個很讓人“感興趣”而又“頗有爭議”的話題,無論是在生物界還是在程式碼的世界中。     Java通過實現Cloneable介面來“說明

11謹慎覆蓋clone

術語:         Clone介面的作用是為了表明類的物件允許克隆,但是Object中的clone方法是受保護的,而沒有提供一個公共可訪問的clone方法。Object中關於clone方法的說明如下: protected Object clone()

10.謹慎改寫clone

    clone是對物件內域的直接複製,當域中有物件引用時,要分清淺複製和深複製。關於深複製淺複製可以參考:https://blog.csdn.net/qq_27469549/article/details/80501284     所以在實現Cloneable介面的時候,

8改寫equals時總是要改寫hashCode

int java.lang.Object.hashCode() Returns a hash code value for the object. This method is supported for the benefit of hashtables such as

10awk進階操作

模式 rpe .sh 定義變量 能夠 all 模式匹配 mon ble 第10章:awk進階操作      在第4章:查找與替換簡單的講解了awk的使用,本章介紹詳細講解awk的使用。awk是一個強大的文本分析工具,簡單的說awk就是把文件逐行的讀

1 了解 Objective-C 語言的起源

還在 特性 只知道 程序 開發 不能 核心 nbsp 原因   馬上就要發布 Swift 4 了,自己也在學習 Swift,後面 iOS 編程估計也快是 Swift 的天下了,我卻還在這抱著一本講 OC 的書在啃,怪只能怪自己之前太懶了,按定價好幾十塊錢買的書不讀完,簡直對

10CSS初始化操作

過程 根據 inpu class 空白 set 防止 auto middle 在寫頁面過程中,每個瀏覽器都會有默認樣式,為了避免瀏覽器的樣式兼容問題,我們會在樣式開始部分對常用標簽進行重置樣式。這樣我們在寫樣式時,就不會有誤差。常用的CSS標簽初始化如下:

《Effective Java 中文版 2版》學習筆記 4通過私有構造器強化不可實例化的能力

缺省 ive ont sof family 其他 筆記 cnblogs ror   只有當類不包含顯式的構造器時,編譯器才會生成一個公有的、無參的缺省構造器。只要讓一個類包含私有構造器,這個類就不能被實例化了。示例: 1 // 工具類 2 public class Uti

《Effective Java 中文版 2版》學習筆記 5避免創建不必要的對象

多余 除了 示例 中文 註意 構造器 stat get tro   最好能重用對象而不是在每次需要的時候就創建一個相同功能的新對象。如果對象是不可變的,它就始終可以被重用。 1 String s = new String("stringette");   每次執行該語句

《Effective Java 中文版 2版》學習筆記 7避免使用終結方法

擁有 fec finalize span fin effect 分布式系 leg 內存   在Java中,當一個對象變得不可到達時,垃圾回收器會回收與該對象相關聯的存儲空間。用try-finally塊來回收其他的非內存資源。   終結方法的缺點在於不能保證會被及時地執行

10路由中的鉤子

export settings pri false ble 裏的 ini min msg 我們知道一個組件從進入到銷毀有很多的鉤子函數,同樣在路由中也設置了鉤子函數。路由的鉤子選項可以寫在路由配置文件中,也可以寫在我們的組件模板中。我們這節課就介紹這兩種鉤子函數的寫法。 路

研發哲學一定要有後備方案

鄭昀 20181109 #哲學 #災備 #devop   過去的九月和十月,厄運接踵而至: 大大小小連續幾次事故。 阿里雲華北機房網路抖動。 網某銀行支付通道抖動。 銀聯支付通道抖動。 某IDC機房出網流量丟包嚴重長達幾十分鐘。   我冷眼旁觀   我

10Python第三方庫概覽

註明:本系列課程專為全國計算機等級考試二級 Python 語言程式設計考試服務 目錄 考綱考點 知識導圖 1、Python第三方庫的獲取和安裝 pip工具安裝 自定義安裝 檔案安裝 Python第三方庫的獲取和安裝 pip工具使用 2、PyInstalle

讀書筆記 ---- 《深入理解Java虛擬機器》---- 10晚期(執行期)優化

上一篇:早期(編譯期)優化:https://blog.csdn.net/pcwl1206/article/details/84635959 目  錄: 1、HotSpot虛擬機器內的即時編譯器 1.1  直譯器與編譯器  1.2  編譯物件與觸

1考慮採用靜態工廠方法代替構造器

第1條:考慮採用靜態工廠方法代替構造器 對類而言,為了讓客戶端獲取它自身的一個例項,最常用的方法就是提供一個公有的構造器。還有一種應該被程式設計師重視的方法:類提供一個公有的靜態工廠方法(static factory method),它只是一個返回類的例項的靜態方法。下面是來自Boolean(基本型別boo

7避免使用終結方法

正常 一個bug c++程序 似的 一個 細節 sta 正是 safety 第7條:避免使用終結方法 終結方法(finalizer)通常是不可預測的,也是很危險的,一般情況下是不必要的。使用終結方法會導致行為不穩定,降低性能以及可移植性問題。 C++程序員被告知&ldq

2遇到多個構造器引數時要考慮用構造器

一、靜態工廠和構造器有個共同的侷限性:它們都不能很好地擴充套件到大量的可選引數。 二、重疊構造器模式可行,但是當有許多引數的時候,客戶端程式碼會很難編寫,並且仍然較難以閱讀—— Demo: 三、遇

3用私有構造器或者列舉類型別強化Singleton屬性

一、公有final域靜態成員 //Singleton with public final field public class Elvis { public static final Elvi

JVM系列10垃圾回收的幾種型別

我們經常會聽到許多垃圾回收的術語,例如:Minor GC、Major GC、Young GC、Old GC、Full GC、Stop-The-World 等。但這些 GC 術語到底指的是什麼,它們之間的區別到底是什麼?今天我們就來詳細說說。 Minor GC 從年輕代空間回收記憶體被稱為 Minor GC