首頁 >Java >Java面試題 >談談你對java中的深克隆和淺克隆的理解

談談你對java中的深克隆和淺克隆的理解

王林
王林轉載
2021-01-30 09:53:352243瀏覽

談談你對java中的深克隆和淺克隆的理解

阿里面試官問題:

談談你對java中的深克隆和淺克隆的理解

回答:

#(說明:本文針對深克隆和淺克隆的區別和實現方式?這個問題)

Talk is cheap

#最近不只一次遇見深淺克隆(深複製,淺複製)的問題,除了印像中有個clone方法外一臉懵逼! ! !克隆(複製)在Java中是一種常見的操作,目的是快速取得一個物件副本。克隆分為深克隆和淺克隆。

淺克隆:建立一個新對象,新對象的屬性和原來對象完全相同,對於非基本型別屬性,仍指向原有屬性所指向的對象的​​記憶體位址。

深克隆:建立一個新對象,屬性中引用的其他對像也會被克隆,不再指向原有對象位址。

總之深淺克隆都會在堆中新分配一塊區域,差異在於物件屬性所引用的物件是否需要進行複製(遞歸性的)。

Show you my picture

#pos:目前物件的位址;

son:son屬性所指向的位址;

name:物件的name屬性。

談談你對java中的深克隆和淺克隆的理解

(相關推薦:java入門教學

Show you my code

#case1:

public class Son implements Serializable , Cloneable{    private String name;    private Son son;    public Son() {        super();
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public Son getSon() {        return son;
    }    public void setSon(Son son) {        this.son = son;
    }    @Override
    public String toString() {        return super.toString();
    }    @Override
    protected Object clone() throws CloneNotSupportedException {        return super.clone();
    }
}

測試

public static void main(String[] args) throws Exception{	// 创建父亲(LiLiu),儿子(LiWu),孙子(LiLiu)并关联
	Son father = new Son();
	father.setName("LiSi");
	Son son = new Son();
	son.setName("LiWu");
	Son grandSon = new Son();
	grandSon.setName("LiLiu");
	father.setSon(son);
	son.setSon(grandSon);	// 调用clone方法
	Son fatherCopy =  (Son) father.clone();	boolean flag1 = fatherCopy==father;	boolean flag2 = fatherCopy.getSon() == son;	boolean flag3 = fatherCopy.getSon().getSon() == grandSon;	// 比较克隆后的地址
	System.out.println(flag1);// false
	System.out.println(flag2);// true
	System.out.println(flag3);// true
	// 比较Name
	flag1= fatherCopy.getName()==father.getName();
	flag2 = fatherCopy.getSon().getName() == son.getName();
	flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName();
	System.out.println(flag1);// true
	System.out.println(flag2);// true
	System.out.println(flag3);// true
	
	//将对象写到流里    
	ByteArrayOutputStream byteOut=new ByteArrayOutputStream();    
	ObjectOutputStream objOut=new ObjectOutputStream(byteOut);    
	objOut.writeObject(father);	//从流里读出来    
	ByteArrayInputStream byteIn=new ByteArrayInputStream(byteOut.toByteArray());    
	ObjectInputStream objInput=new ObjectInputStream(byteIn);
    fatherCopy = (Son) objInput.readObject();
	flag1= fatherCopy==father;
	flag2 = fatherCopy.getSon() == son;
	flag3 = fatherCopy.getSon().getSon() == grandSon;
	System.out.println(flag1);// false
	System.out.println(flag2);// false
	System.out.println(flag3);// false
	
	// 比较Name
	flag1= fatherCopy.getName()==father.getName();
	flag2 = fatherCopy.getSon().getName() == son.getName();
	flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName();
	System.out.println(flag1);// false
	System.out.println(flag2);// false
	System.out.println(flag3);// false}

從上文程式碼及運行結果不難看出,如果物件實作Cloneable並重寫clone方法不進行任何操作時,呼叫clone是進行的淺克隆。而使用物件流將物件寫入流然後再讀出是進行的深克隆。

思考:既然實作Cloneable介面並重寫clone介面只能進行淺克隆。但如果類別的參考型別屬性(以及屬性的參考型別屬性)都進行淺克隆,直到沒有引用型別屬性或引用型別屬性為null時,整體上就形成了深克隆。既物件的參考型別屬性和屬性的應用型別屬性都實作Coloneable,重寫clone方法並在clone方法中進行呼叫。

protected Object clone() throws CloneNotSupportedException {
      Son result = (Son) super.clone();	if (son != null) {
		result.son = (Son) son.clone();
	}    return result;
}

個人認為,在選擇深克隆方法時,應根據物件的複雜程度,如引用類型屬性是否有多層引用類型屬性關係。若物件只有一層或兩層引用類型的屬性,選擇思考中所提到的方法較為方便,反之則使用物件流。

更多相關面試題請上:java面試題目及答案

以上是談談你對java中的深克隆和淺克隆的理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除