天天看點

關于Object類的clone()方法

clone()方法是用于淺克隆或者深克隆一個java對象的,但是要注意一個誤區:clone方法是Object類的,并不是Cloneable接口的,Cloneable隻是一個标記接口,标記接口是用于标記實作該接口的類具有某種該接口标記的功能,常見的标記接口有三個:Serializable、Cloneable、RandomAccess,沒有實作Cloneable接口,那麼調用clone方法就會爆出CloneNotSupportedException異常。

要使得一個java類可以實作克隆,那麼該類就需要實作Cloneable接口,并且重寫基類Object的clone方法,其實Object的clone方法就已經預設有克隆的能力了,并且實作的是淺克隆,那為什麼一定得重寫clone方法呢?

我們先來看Object類的clone方法源碼:

可以看到,該方法非常之特殊:

  1. 方法被native關鍵字修飾,并且該方法沒有方法體,沒有方法體的方法我們認為是抽象方法,可是Object類并不是一個抽象類,而是一個具體類,那為什麼還能容納抽象方法呢,其實就是native關鍵字在起作用,被native關鍵字修飾的方法屬于本地方法,表示Java的作用範圍已經無法達到,底層會去調用C語言或者C++的庫。
  2. 該方法是被protected修飾,這就表明我們在子類中不重寫此方法,就在子類外無法通路,因為這個protected權限是僅僅能在Object所在的包和子類能通路的,這也驗證了子類重寫父類方法權限修飾符可以變大但不能變小的說法。

是以我們要使得一個類具有clone的能力,可以先實作Cloneable接口,再重寫clone方法,方法内部去調用了父類的clone方法,其實是為了擴大通路權限,也可以把protected改為public,以後再繼承就不用重寫了。當然這隻是淺克隆的clone函數,深克隆就需要修改clone的方法體了。

public class Mytest implements  Cloneable{
    /**
     * 重寫clone方法,調用父類預設的clone方法,實作的是淺克隆
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}