1. 程式人生 > >賦值、淺拷貝和深拷貝

賦值、淺拷貝和深拷貝

直接賦值

  先定義了一個變數a,然後將a變數賦值給b。則a、b兩個變數都指向記憶體中同一個物件。

public static <T> T[] extendsArray(T[] data){

    int newLength = (data.length * 3)/2 + 1;

    return Arrays.copyOf(data, newLength);
}

public static void main(String[] args) {

    TestClass[] arr = new TestClass[10];
    arr[0] = new TestClass("yanjun"
, 24); TestClass[] arr2 = extendsArray(arr); arr2[0].setAge(18); System.out.println("arr[0].age: " + arr[0].getAge());//輸出18 System.out.println("arr2[0].age: " + arr2[0].getAge());//輸出18 }

淺拷貝

  如果先定義一個a變數,然後使用clone方法拷貝一份給b變數。這實際上是建立一個新的物件給b變數,然後將a變數指向的物件的屬性賦值給b變數指向的物件。這是淺拷貝,它對於基本資料型別和String的屬性是實現了拷貝,但是對於引用型別的屬性(如本例中的cat),兩個物件是指向同一個物件。

public static void main(String[] args) {

    TestClass aaa = new TestClass("yanjun", 23);
    aaa.getCat().setColor("red");
    aaa.getCat().setSize(23);

    TestClass bbb = (TestClass) aaa.clone();

    aaa.setName("new yanjun");
    aaa.setAge(18);
    aaa.getCat().setColor("blue");
    aaa.getCat().setSize(18
); System.out.println(aaa.getName() + "--------" + bbb.getName()); //輸出new yanjun--------yanjun System.out.println(aaa.getAge() + "--------" + bbb.getAge());//輸出18--------23 System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//輸出blue--------blue System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//輸出18--------18 } class TestClass implements Cloneable{ private String name; private int age; private Cat cat; public TestClass(String name, int age){ this.name = name; this.age = age; this.cat = new Cat(); } //省去get和set方法 public Object clone(){ Object o=null; try{ o=(TestClass)super.clone();//Object 中的clone()識別出你要複製的是哪一個物件。 } catch(CloneNotSupportedException e){ System.out.println(e.toString()); } return o; } } class Cat{ private String color; private int size; //省去get和set方法 public Cat() { this.color = "red"; this.size = 23; } }

深拷貝

  深拷貝有兩種方式實現:層層clone的方法和利用序列化來做深拷貝

1、層層clone的方法

  在淺拷貝的基礎上實現,給引用型別的屬性新增克隆方法,並且在拷貝的時候也實現引用型別的拷貝。此種方法由於要在多個地方實現拷貝方法,可能會造成混論。

public static void main(String[] args) {

    TestClass aaa = new TestClass("yanjun", 23);
    aaa.getCat().setColor("red");
    aaa.getCat().setSize(23);

    TestClass bbb = (TestClass) aaa.clone();

    aaa.setName("new yanjun");
    aaa.setAge(18);
    aaa.getCat().setColor("blue");
    aaa.getCat().setSize(18);

    System.out.println(aaa.getName() + "--------" + bbb.getName()); //輸出new yanjun--------yanjun
    System.out.println(aaa.getAge() + "--------" + bbb.getAge());//輸出18--------23
    System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//輸出blue--------red
    System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//輸出18--------23

}

class TestClass implements Cloneable{

    private String name;
    private int age;
    private Cat cat;

    public TestClass(String name, int age){
        this.name = name;
        this.age = age;
        this.cat = new Cat();
    }
    //省去get和set方法
    public Object clone(){ 
        TestClass o=null; 
        try{ 
            o=(TestClass)super.clone();//Object 中的clone()識別出你要複製的是哪一個物件。 
        } 
        catch(CloneNotSupportedException e){ 
            System.out.println(e.toString()); 
        } 
        o.cat = (Cat)o.cat.clone();
        return o; 
    }  
}

class Cat{
    private String color;
    private int size;
    //省去get和set方法
    public Cat() {
        this.color = "red";
        this.size = 23;
    }
    public Object clone(){ 
        Object o=null; 
        try{ 
            o=(Cat)super.clone();//Object 中的clone()識別出你要複製的是哪一個物件。 
        } 
        catch(CloneNotSupportedException e){ 
            System.out.println(e.toString()); 
        } 
        return o; 
    }  
}
2、利用序列化來做深拷貝

  為避免複雜物件中使用clone方法可能帶來的換亂,可以使用串化來實現深拷貝。先將物件寫到流裡,然後再重流裡讀出來。

public Object deepClone() throws IOException, ClassNotFoundException
{ 
    //將物件寫到流裡 
    ByteArrayOutputStream bo=new ByteArrayOutputStream(); 
    ObjectOutputStream oo=new ObjectOutputStream(bo); 
    oo.writeObject(this); 
    //從流裡讀出來 
    ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); 
    ObjectInputStream oi=new ObjectInputStream(bi); 
    return(oi.readObject()); 
}