1. 程式人生 > 實用技巧 >Java-Object.clone()-淺複製與深複製

Java-Object.clone()-淺複製與深複製

引言

在某些場景中,我們需要獲取到一個物件的拷貝用於某些處理。這時候就可以用到Java中的Object.clone方法進行物件複製,得到一個一模一樣的新物件。但是在實際使用過程中會發現:當物件中含有可變的引用型別屬性時,在複製得到的新物件對該引用型別屬性內容進行修改,原始物件響應的屬性內容也會發生變化,這就是"淺拷貝"的現象。

淺拷貝的例子

Address類:clone/Address.java

package clone;

public class Address implements Cloneable{//實現cloneable介面
    private String province;
    
private String city; public Address() { } public Address(String province, String city) { this.province = province; this.city = city; } public Address clone() throws CloneNotSupportedException { Address newAdd = (Address)super.clone(); return
newAdd; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; }
public String toString() { return "Province:"+province+" city:"+city; } }

student類:clone/student.java

package clone;

public class student implements Cloneable{
    private String name;//String被宣告為final,是不可變型別,無法修改,所以就算是淺複製也不影響。
    private int age;//基本型別,clone的時候直接copy
    private Address address;//Address不是基本型別,並且可變,預設的clone的時候只會複製一個引用,這樣clone前後的兩個物件都引用同一個Address例項物件。
    public student() {
        
    }
    public student(String name,int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public student clone() throws CloneNotSupportedException {
        student newStu = (student) super.clone();
        newStu.address = (Address) address.clone();//不加這一句,對於Address來說就是一個淺複製。
        return newStu;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public String toString() {
        return "name:"+name+"   age:"+age+"Address Info:"+address.toString();
    }
}

test類: clone/test.java

package clone;

public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address add = new Address("四川","成都");
        student a = new student("小明",18,add);
        
        student b = a.clone();//克隆a,賦值給b
        add.setCity("廣安");//淺複製的話,a和b都引用add這個例項物件,則此次修改值勢必會影響a和b。深複製則不影響。
        System.out.println(a.toString());
        System.out.println(b.toString());
    }
}

輸出

name:小明   age:18Address Info:Province:四川   city:廣安
name:小明   age:18Address Info:Province:四川   city:成都

從輸出結果來看,對add例項物件的修改並沒有影響到b這個引用變數,所以本次clone不是淺複製。