欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的clone()和Cloneable接口實(shí)例

 更新時(shí)間:2021年11月03日 09:39:35   作者:lylodlig  
這篇文章主要介紹了Java中的clone()和Cloneable接口實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

clone()和Cloneable接口

clone顧名思義就是克隆,即,復(fù)制一個(gè)相等的對(duì)象,但是不同的引用地址。

我們知道拿到一個(gè)對(duì)象的地址,只要提供相應(yīng)的方法就可以修改這個(gè)對(duì)象,但是如果我們想要得到這個(gè)對(duì)象去修改它,又想保留這個(gè)對(duì)象原來(lái)的屬性,這是就可以使用clone(),它會(huì)復(fù)制一個(gè)內(nèi)容相同的對(duì)象而具有不同內(nèi)存地址。

Cloneable接口,就是我們要使用clone()必須實(shí)現(xiàn)的接口,不然會(huì)拋出異常。

public class Bean implements Cloneable {
    private String a; 
    public Bean(String a) {
        this.a = a;
    }
 
    public String getA() {
        return a;
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    @Override
    public boolean equals(Object o) {
        if(o instanceof Bean){
            Bean bean = (Bean) o;
            return bean.getA().equals(a);
        }
        return false;
    }
}

在Cloneable 接口中并沒有給我們定義任何方法

這里需要重寫clone()方法

protected native Object clone() throws CloneNotSupportedException;
protected Object clone() throws CloneNotSupportedException {
        if (!(this instanceof Cloneable)) {
            throw new CloneNotSupportedException("Class " + getClass().getName() +
                                                 " doesn't implement Cloneable");
        } 
        return internalClone();
    }

它是Object類里面的native方法,它是protected的,根據(jù)需要可以寫為public,可以看到如果不實(shí)現(xiàn)Cloneable接口將會(huì)拋出CloneNotSupportedException 異常。

測(cè)試一下

try { 
            Bean a = new Bean("lzy");
            Bean b = a;
            Bean c = (Bean) a.clone();
 
            Log.i(TAG, "onCreate: " + (a == b));         //true
            Log.i(TAG, "onCreate: " + (a.equals(b)));    //true
 
            Log.i(TAG, "onCreate: " + (a == c));         //false
            Log.i(TAG, "onCreate: " + (a.equals(c)));    //true
  
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

可以看到克隆出來(lái)的類的地址是不同的,而內(nèi)容是相同的。

下面修改一下,在Bean加一個(gè)成員變量ChildBean

public class ChildBean implements Cloneable {
    private String c;
    public String getC() {
        return c;
    }
    public ChildBean(String c) {
        this.c = c;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public boolean equals(Object o) {
        if (o instanceof ChildBean) {
            ChildBean bean = (ChildBean) o;
            return bean.getC().equals(c);
        }
        return false;
    }
}
public class Bean implements Cloneable {
    private String a;
    private ChildBean childBean; 
    public Bean(String a, ChildBean childBean) {
        this.a = a;
        this.childBean = childBean;
    }
    public String getA() {
        return a;
    }
 
    public ChildBean getChildBean() {
        return childBean;
    }
 
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    @Override
    public boolean equals(Object o) {
        if (o instanceof Bean) {
            Bean bean = (Bean) o;
            return bean.getA().equals(a);
        }
        return false;
    }
}
Bean a = new Bean("lzy", new ChildBean("child"));
            Bean b = a;
            Bean c = (Bean) a.clone();
 
            Log.i(TAG, "onCreate: " + (a.getChildBean() == b.getChildBean()));         //true
            Log.i(TAG, "onCreate: " + (a.getChildBean().equals(b.getChildBean())));    //true
 
            Log.i(TAG, "onCreate: " + (a.getChildBean() == c.getChildBean()));         //true
            Log.i(TAG, "onCreate: " + (a.getChildBean().equals(c.getChildBean())));    //true

測(cè)試發(fā)現(xiàn)有一個(gè)結(jié)果不是我們所預(yù)期的,這意味著并沒有真正克隆ChildBean,只是克隆的它的內(nèi)存地址,導(dǎo)致兩個(gè)具有相同的內(nèi)存地址,這也就是淺克隆,此時(shí)我們需要的是深克隆,需要按照下面方法修改,重寫clone()方法

  @Override
    public Object clone() throws CloneNotSupportedException {
        Bean bean = (Bean) super.clone();
        bean.childBean = (ChildBean) bean.childBean.clone();
        return bean;
    }

但是這樣做如果有很多層的類,那每一層都需要去重寫,顯得很麻煩。所以我們可以用下面的工具類來(lái)實(shí)現(xiàn)

public class BeanUtil {
    public static <T> T cloneTo(T src) throws RuntimeException {
        ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
        ObjectOutputStream out = null;
        ObjectInputStream in = null;
        T dist = null;
        try {
            out = new ObjectOutputStream(memoryBuffer);
            out.writeObject(src);
            out.flush();
            in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
            dist = (T) in.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (out != null)
                try {
                    out.close();
                    out = null;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            if (in != null)
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
        }
        return dist;
    }
}
Bean a = new Bean("lzy", new ChildBean("child"));
        Bean b = BeanUtil.cloneTo(a); 
        Log.i(TAG, "onCreate: " + (a.getChildBean() == b.getChildBean()));         //false
        Log.i(TAG, "onCreate: " + (a.getChildBean().equals(b.getChildBean())));    //true

這樣就可以很輕松的得到我們預(yù)期的結(jié)果,但是記得每一個(gè)類都要去 實(shí)現(xiàn)Serializable接口。

Cloneable和clone()的總結(jié)

1.Cloneable 的用途

Cloneable和Serializable一樣都是標(biāo)記型接口,它們內(nèi)部都沒有方法和屬性,implements Cloneable表示該對(duì)象能被克隆,能使用Object.clone()方法。如果沒有implements Cloneable的類調(diào)用Object.clone()方法就會(huì)拋出CloneNotSupportedException。

2.克隆的分類

(1)淺克?。╯hallow clone),淺拷貝是指拷貝對(duì)象時(shí)僅僅拷貝對(duì)象本身和對(duì)象中的基本變量,而不拷貝對(duì)象包含的引用指向的對(duì)象。

(2)深克?。╠eep clone),深拷貝不僅拷貝對(duì)象本身,而且拷貝對(duì)象包含的引用指向的所有對(duì)象。

舉例區(qū)別一下:對(duì)象A1中包含對(duì)B1的引用,B1中包含對(duì)C1的引用。淺拷貝A1得到A2,A2中依然包含對(duì)B1的引用,B1中依然包含對(duì)C1的引用。深拷貝則是對(duì)淺拷貝的遞歸,深拷貝A1得到A2,A2中包含對(duì)B2(B1的copy)的引用,B2中包含對(duì)C2(C1的copy)的引用。

3.克隆的舉例

要讓一個(gè)對(duì)象進(jìn)行克隆,其實(shí)就是兩個(gè)步驟:

1.讓該類實(shí)現(xiàn)java.lang.Cloneable接口;

2.重寫(override)Object類的clone()方法。

public class Wife implements Cloneable {  
    private int id;  
    private String name;  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public Wife(int id,String name) {  
        this.id = id;  
        this.name = name;  
    }  
    @Override  
    public int hashCode() {//myeclipse自動(dòng)生成的  
        final int prime = 31;  
        int result = 1;  
        result = prime * result + id;  
        result = prime * result + ((name == null) ? 0 : name.hashCode());  
        return result;  
    }  
    @Override  
    public boolean equals(Object obj) {//myeclipse自動(dòng)生成的  
        if (this == obj)  
            return true;  
        if (obj == null)  
            return false;  
        if (getClass() != obj.getClass())  
            return false;  
        Wife other = (Wife) obj;  
        if (id != other.id)  
            return false;  
        if (name == null) {  
            if (other.name != null)  
                return false;  
        } else if (!name.equals(other.name))  
            return false;  
        return true;  
    }  
    @Override  
    public Object clone() throws CloneNotSupportedException {  
        return super.clone();  
    }  
    /** 
     * @param args 
     * @throws CloneNotSupportedException  
     */  
    public static void main(String[] args) throws CloneNotSupportedException {  
        Wife wife = new Wife(1,"wang");  
        Wife wife2 = null;  
        wife2 = (Wife) wife.clone();  
        System.out.println("class same="+(wife.getClass()==wife2.getClass()));//true  
        System.out.println("object same="+(wife==wife2));//false  
        System.out.println("object equals="+(wife.equals(wife2)));//true  
    }  
}  

4.淺克隆的舉例

public class Husband implements Cloneable {  
    private int id;  
    private Wife wife;  
    public Wife getWife() {  
        return wife;  
    }  
    public void setWife(Wife wife) {  
        this.wife = wife;  
    }  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public Husband(int id) {  
        this.id = id;  
    }  
    @Override  
    public int hashCode() {//myeclipse自動(dòng)生成的  
        final int prime = 31;  
        int result = 1;  
        result = prime * result + id;  
        return result;  
    }  
    @Override  
    protected Object clone() throws CloneNotSupportedException {  
        return super.clone();  
    }  
    @Override  
    public boolean equals(Object obj) {//myeclipse自動(dòng)生成的  
        if (this == obj)  
            return true;  
        if (obj == null)  
            return false;  
        if (getClass() != obj.getClass())  
            return false;  
        Husband other = (Husband) obj;  
        if (id != other.id)  
            return false;  
        return true;  
    }  
    /** 
     * @param args 
     * @throws CloneNotSupportedException  
     */  
    public static void main(String[] args) throws CloneNotSupportedException {  
        Wife wife = new Wife(1,"jin");  
        Husband husband = new Husband(1);  
        Husband husband2 = null;  
        husband.setWife(wife);  
        husband2 = (Husband) husband.clone();  
        System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true  
        System.out.println("husband object same="+(husband==husband2));//false  
        System.out.println("husband object equals="+(husband.equals(husband)));//true  
        System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true  
        System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//true  
        System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true  
    }  
}  

5.深克隆的舉例

如果要深克隆,需要重寫(override)Object類的clone()方法,并且在方法內(nèi)部調(diào)用持有對(duì)象的clone()方法;注意如下代碼的clone()方法

public class Husband implements Cloneable {  
    private int id;  
    private Wife wife;  
    public Wife getWife() {  
        return wife;  
    }  
    public void setWife(Wife wife) {  
        this.wife = wife;  
    }  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public Husband(int id) {  
        this.id = id;  
    }  
    @Override  
    public int hashCode() {//myeclipse自動(dòng)生成的  
        final int prime = 31;  
        int result = 1;  
        result = prime * result + id;  
        return result;  
    }  
    @Override  
    protected Object clone() throws CloneNotSupportedException {  
        Husband husband = (Husband) super.clone();  
        husband.wife = (Wife) husband.getWife().clone();  
        return husband;  
    }  
    @Override  
    public boolean equals(Object obj) {//myeclipse自動(dòng)生成的  
        if (this == obj)  
            return true;  
        if (obj == null)  
            return false;  
        if (getClass() != obj.getClass())  
            return false;  
        Husband other = (Husband) obj;  
        if (id != other.id)  
            return false;  
        return true;  
    }  
    /** 
     * @param args 
     * @throws CloneNotSupportedException  
     */  
    public static void main(String[] args) throws CloneNotSupportedException {  
        Wife wife = new Wife(1,"jin");  
        Husband husband = new Husband(1);  
        Husband husband2 = null;  
        husband.setWife(wife);  
        husband2 = (Husband) husband.clone();  
        System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true  
        System.out.println("husband object same="+(husband==husband2));//false  
        System.out.println("husband object equals="+(husband.equals(husband)));//true  
        System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true  
        System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//false  
        System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true  
    }  
}  

但是也有不足之處,如果Husband內(nèi)有N個(gè)對(duì)象屬性,突然改變了類的結(jié)構(gòu),還要重新修改clone()方法。

解決辦法:可以使用Serializable運(yùn)用反序列化手段,調(diào)用java.io.ObjectInputStream對(duì)象的 readObject()方法。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • JFINAL+Ajax傳參 array 數(shù)組方法 獲取request中數(shù)組操作

    JFINAL+Ajax傳參 array 數(shù)組方法 獲取request中數(shù)組操作

    這篇文章主要介紹了JFINAL+Ajax傳參 array 數(shù)組方法 獲取request中數(shù)組操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • 淺析JPA分類表的操作函數(shù)

    淺析JPA分類表的操作函數(shù)

    這篇文章主要介紹了JPA分類表的操作函數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-02-02
  • java 圖片與base64相互轉(zhuǎn)化的示例

    java 圖片與base64相互轉(zhuǎn)化的示例

    這篇文章主要介紹了java 圖片與base64相互轉(zhuǎn)化的示例,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-10-10
  • SpringBoot+MyBatis實(shí)現(xiàn)登錄案例

    SpringBoot+MyBatis實(shí)現(xiàn)登錄案例

    前端時(shí)間在網(wǎng)上看到有朋友在學(xué)習(xí)springboot項(xiàng)目的搭建過(guò)程,今天就抽空給大家分享一個(gè)案例幫助大家學(xué)習(xí)SpringBoot+MyBatis實(shí)現(xiàn)登錄功能,具體實(shí)現(xiàn)代碼跟隨小編一起看看吧
    2021-06-06
  • Guava反射工具使用示例詳解

    Guava反射工具使用示例詳解

    這篇文章主要為大家介紹了Guava反射工具使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • java selenium教程環(huán)境搭建方法

    java selenium教程環(huán)境搭建方法

    本文主要介紹java selenium 環(huán)境搭建,這里詳細(xì)介紹了selenium的安裝環(huán)境搭建,有興趣的小伙伴可以參考下
    2016-08-08
  • 詳細(xì)了解MyBatis的異常處理機(jī)制

    詳細(xì)了解MyBatis的異常處理機(jī)制

    本文將對(duì)MyBatis的異常體系以及異常使用進(jìn)行學(xué)習(xí),MyBatis版本是3.5.6,作為一款成熟的ORM框架,MyBatis有自己一套成熟的異常處理體系,,需要的朋友可以參考下
    2023-06-06
  • JavaScript中棧和隊(duì)列應(yīng)用詳情

    JavaScript中棧和隊(duì)列應(yīng)用詳情

    這篇文章主要介紹了JavaScript中棧和隊(duì)列應(yīng)用詳情,棧如果用數(shù)組模擬的話是類似于一個(gè)U形桶狀堆棧空間,文章圍繞制圖展開詳細(xì)的內(nèi)容展開更多相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-06-06
  • 詳解Mybatis中的 ${} 和 #{}區(qū)別與用法

    詳解Mybatis中的 ${} 和 #{}區(qū)別與用法

    這篇文章主要介紹了Mybatis中的 ${} 和 #{}區(qū)別與用法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • mybatis 解決將數(shù)值0識(shí)別成空字符串的問題

    mybatis 解決將數(shù)值0識(shí)別成空字符串的問題

    這篇文章主要介紹了mybatis 解決將數(shù)值0識(shí)別成空字符串的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評(píng)論