天天看點

淺克隆、深克隆// ———-1、直接複制對象 ———–// ——–2、淺克隆 裡面沒有引用對象—// ———-3、淺克隆 裡面有被引用對象// ———–4、深克隆 裡面有被引用對象———-

// ———-1、直接複制對象 ———–

package ninthTestModel;

/*
 * 淺克隆
 * 深克隆
 * 序列化。
 * 差別在于對象有引用對象的時候 一個是指向同一個引用對象 一個是指向不同對象
 */

/*
 *      
 *   【淺克隆】,通常隻是對克隆的執行個體進行複制,但裡面的其他子對象,都是共用的。
   *   【深克隆】,克隆的時候會複制它的子對象的引用,裡面所有的變量和子對象都是又額外拷貝了一份。
 * 
 */


// 周報
class WeekdayInformation{
    public String strInformation;   // 事件
    public String strTime;          // 時間
    public String strLocation;      // 地點

    public String getStrInformation() {
        return strInformation;
    }
    public String getStrTime() {
        return strTime;
    }
    public String getStrLocation() {
        return strLocation;
    }
    public void setStrInformation(String strInformation) {
        this.strInformation = strInformation;
    }
    public void setStrTime(String strTime) {
        this.strTime = strTime;
    }
    public void setStrLocation(String strLocation) {
        this.strLocation = strLocation;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub



        return "事件:"+strInformation+"\t時間:"+strTime+"\t地點:"+strLocation;
    }
}


public class CloneModel {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        WeekdayInformation weekdayInformation=new WeekdayInformation();
        weekdayInformation.setStrInformation("吃飯");
        weekdayInformation.setStrTime("周一");
        weekdayInformation.setStrLocation("食堂");
        System.out.println(weekdayInformation.toString()); // [email protected]

        WeekdayInformation week2=weekdayInformation;
        System.out.println(week2.toString());

        System.out.println("***********************");

        /*
         * weekdayInformation修改資訊 則week2的資訊也修改
         */
        System.out.println("weekdayInformation修改了資訊:");
        weekdayInformation.setStrTime("周二");
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

        System.out.println("***********************");


        /*
         * week2修改資訊 則weekdayInformation的資訊也修改
         */
        System.out.println("week2修改了資訊:");
        week2.setStrTime("周一");
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

    }
}

/*
結果如下:

事件:吃飯   時間:周一   地點:食堂
事件:吃飯   時間:周一   地點:食堂
***********************
weekdayInformation修改了資訊:
事件:吃飯   時間:周二   地點:食堂
事件:吃飯   時間:周二   地點:食堂
***********************
week2修改了資訊:
事件:吃飯   時間:周一   地點:食堂
事件:吃飯   時間:周一   地點:食堂

*/
           

// ——–2、淺克隆 裡面沒有引用對象—

package ninthTestModel;

/*
 * 淺克隆
 * 深克隆
 * 序列化。
 * 差別在于對象有引用對象的時候 一個是指向同一個引用對象 一個是指向不同對象
 */

/*
 *      
 *   【淺克隆】,通常隻是對克隆的執行個體進行複制,但裡面的其他子對象,都是共用的。
   *   【深克隆】,克隆的時候會複制它的子對象的引用,裡面所有的變量和子對象都是又額外拷貝了一份。
 * 
 */

// 周報
class WeekdayInformation implements Cloneable{
    public String strInformation;   // 事件
    public String strTime;          // 時間
    public String strLocation;      // 地點

    public String getStrInformation() {
        return strInformation;
    }
    public String getStrTime() {
        return strTime;
    }
    public String getStrLocation() {
        return strLocation;
    }
    public void setStrInformation(String strInformation) {
        this.strInformation = strInformation;
    }
    public void setStrTime(String strTime) {
        this.strTime = strTime;
    }
    public void setStrLocation(String strLocation) {
        this.strLocation = strLocation;
    }

    // 淺克隆
    @Override
    protected WeekdayInformation clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
            Object object=null;

            object=super.clone();
            System.out.println("淺克隆");
            return (WeekdayInformation) object;

            // TODO Auto-generated catch block






    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "事件:"+strInformation+"\t時間:"+strTime+"\t地點:"+strLocation;
    }
}


public class CloneModel {

    public static void main(String[] args) throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        WeekdayInformation weekdayInformation=new WeekdayInformation();
        weekdayInformation.setStrInformation("吃飯");
        weekdayInformation.setStrTime("周一");
        weekdayInformation.setStrLocation("食堂");
        System.out.println(weekdayInformation.toString()); // [email protected]

        WeekdayInformation week2=weekdayInformation.clone();
        System.out.println(week2.toString());

        System.out.println("***********************");

        /*
         * weekdayInformation修改資訊 則week2的資訊也修改
         */
        System.out.println("weekdayInformation修改了資訊:");
        weekdayInformation.setStrTime("周二。");
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

        System.out.println("***********************");


        /*
         * week2修改資訊 則weekdayInformation的資訊也修改
         */
        System.out.println("week2修改了資訊:");
        week2.setStrTime("周三。");
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

    }

}

結果如下:
/*
    事件:吃飯   時間:周一   地點:食堂
    淺克隆
    事件:吃飯   時間:周一   地點:食堂
    ***********************
    weekdayInformation修改了資訊:
    事件:吃飯   時間:周二。  地點:食堂
    事件:吃飯   時間:周一   地點:食堂
    ***********************
    week2修改了資訊:
    事件:吃飯   時間:周二。  地點:食堂
    事件:吃飯   時間:周三。  地點:食堂
*/



           

// ———-3、淺克隆 裡面有被引用對象

package ninthTestModel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;

import sixTestOop.TestEighthToString;

/*
 * 淺克隆
 * 深克隆
 * 序列化。
 * 差別在于對象有引用對象的時候 一個是指向同一個引用對象 一個是指向不同對象
 */

/*
 *      
 *   【淺克隆】,通常隻是對克隆的執行個體進行複制,但裡面的其他子對象,都是共用的。
   *   【深克隆】,克隆的時候會複制它的子對象的引用,裡面所有的變量和子對象都是又額外拷貝了一份。
 *      注:!序列化問題 因為使用了序列化方法實作深克隆 是以類需要繼承Serializable 引用類也需要繼承
 */

class TestClone implements Serializable{
    public String testString;
    public void setTestString(String testString) {
        this.testString = testString;
    }
    public String getTestString() {
        return testString;
    }

}

// 周報
class WeekdayInformation implements Cloneable,Serializable{
    public String strInformation;   // 事件
    public String strTime;          // 時間
    public String strLocation;      // 地點
    public TestClone strClone;      // 被引用對象 


    public String getStrInformation() {
        return strInformation;
    }
    public String getStrTime() {
        return strTime;
    }
    public String getStrLocation() {
        return strLocation;
    }
    public TestClone getStrClone() {
        return strClone;
    }

    public void setStrInformation(String strInformation) {
        this.strInformation = strInformation;
    }
    public void setStrTime(String strTime) {
        this.strTime = strTime;
    }
    public void setStrLocation(String strLocation) {
        this.strLocation = strLocation;
    }
    public void setStrClone(TestClone strClone) {
        this.strClone = strClone;
    }

    // 淺克隆

    @Override
    protected WeekdayInformation clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Object object=null;

        object=super.clone();
        System.out.println("淺克隆");
        return (WeekdayInformation) object;

    }



    // 深克隆
    public WeekdayInformation deepClone() throws IOException, ClassNotFoundException,OptionalDataException {
        System.out.println("******深克隆*********\n");

        WeekdayInformation weekdayInformation=null;

        // -- 将對象寫入流中
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
        oos.close();

        // -- 将對象從流中取出
        ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);
        weekdayInformation=(WeekdayInformation) ois.readObject();
        ois.close();


        return weekdayInformation;

    }




    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "事件:"+strInformation+"\t時間:"+strTime+"\t地點:"+strLocation+"\t測試:"+strClone.getTestString();
    }
}


public class CloneModel {

    public static void main(String[] args) throws CloneNotSupportedException, OptionalDataException, ClassNotFoundException, IOException {
        // TODO Auto-generated method stub
        WeekdayInformation weekdayInformation=new WeekdayInformation();
        TestClone testClone=new TestClone();
        testClone.setTestString("test");
        weekdayInformation.setStrInformation("吃飯");
        weekdayInformation.setStrTime("周一");
        weekdayInformation.setStrLocation("食堂");
        weekdayInformation.setStrClone(testClone);
        System.out.println(weekdayInformation.toString()); //如果沒重寫toString()方法顯示: [email protected]


        WeekdayInformation  week2 = weekdayInformation.clone();

        System.out.println("克隆資訊如下:"+week2+"\n");



        System.out.println("克隆對象是否相同:"+(weekdayInformation==week2));//

        //?? 為什麼兩個都相同了?? 因為指向的同一個對象
        System.out.println("被引用對象TestClone是否相同:"+(weekdayInformation.getStrClone()==week2.getStrClone())); //相同? --相同
        System.out.println("基本對象String是否相同:"+(weekdayInformation.getStrInformation()==week2.getStrInformation())); //相同? -- 相同
        System.out.println("***********\n");

        System.out.println(week2.toString());

        System.out.println("***********************");

        /*
         * weekdayInformation修改資訊 則week2的資訊也修改
         */
        TestClone testClone1=new TestClone();
        testClone1.setTestString("test1");

        System.out.println("weekdayInformation修改了資訊:");
        weekdayInformation.setStrTime("周二");
        weekdayInformation.setStrClone(testClone1); 
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

        System.out.println("***********************");


        /*
         * week2修改資訊 則weekdayInformation的資訊也修改
         */
        TestClone testClone2=new TestClone();
        testClone2.setTestString("test2");
        System.out.println("week2修改了資訊:");
        week2.setStrTime("周三");
        week2.setStrClone(testClone2);  
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

    }

}
/*
輸出結果如下:

    事件:吃飯   時間:周一   地點:食堂   測試:test
    淺克隆
    克隆資訊如下:事件:吃飯    時間:周一   地點:食堂   測試:test

    克隆對象是否相同:false
    被引用對象TestClone是否相同:true
    基本對象String是否相同:true
    ***********

    事件:吃飯   時間:周一   地點:食堂   測試:test
    ***********************
    weekdayInformation修改了資訊:
    事件:吃飯   時間:周二   地點:食堂   測試:test1
    事件:吃飯   時間:周一   地點:食堂   測試:test
    ***********************
    week2修改了資訊:
    事件:吃飯   時間:周二   地點:食堂   測試:test1
    事件:吃飯   時間:周三   地點:食堂   測試:test2


*/
           

// ———–4、深克隆 裡面有被引用對象———-

package ninthTestModel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import sixTestOop.TestEighthToString;

/*
 * 淺克隆
 * 深克隆
 * 序列化。
 * 差別在于對象有引用對象的時候 一個是指向同一個引用對象 一個是指向不同對象
 */

/*
 *      
 *   【淺克隆】,通常隻是對克隆的執行個體進行複制,但裡面的其他子對象,都是共用的。
   *   【深克隆】,克隆的時候會複制它的子對象的引用,裡面所有的變量和子對象都是又額外拷貝了一份。
 * 
 */

class TestClone{
    public String testString;
    public void setTestString(String testString) {
        this.testString = testString;
    }
    public String getTestString() {
        return testString;
    }

}

// 周報
class WeekdayInformation implements Cloneable{
    public String strInformation;   // 事件
    public String strTime;          // 時間
    public String strLocation;      // 地點
    public TestClone strClone;      // 被引用對象 


    public String getStrInformation() {
        return strInformation;
    }
    public String getStrTime() {
        return strTime;
    }
    public String getStrLocation() {
        return strLocation;
    }
    public TestClone getStrClone() {
        return strClone;
    }

    public void setStrInformation(String strInformation) {
        this.strInformation = strInformation;
    }
    public void setStrTime(String strTime) {
        this.strTime = strTime;
    }
    public void setStrLocation(String strLocation) {
        this.strLocation = strLocation;
    }
    public void setStrClone(TestClone strClone) {
        this.strClone = strClone;
    }

    // 淺克隆

    @Override
    protected WeekdayInformation clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Object object=null;

        object=super.clone();
        System.out.println("淺克隆");
        return (WeekdayInformation) object;

    }



    // 深克隆
    public WeekdayInformation deepClone() throws IOException, ClassNotFoundException {
        // -- 将對象寫入流中
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);

        // -- 将對象從流中取出
        ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);

        return (WeekdayInformation) ois.readObject();


    }




    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "事件:"+strInformation+"\t時間:"+strTime+"\t地點:"+strLocation+"\t測試:"+strClone.getTestString();
    }
}


public class CloneModel {

    public static void main(String[] args) throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        WeekdayInformation weekdayInformation=new WeekdayInformation();
        TestClone testClone=new TestClone();
        testClone.setTestString("test");
        weekdayInformation.setStrInformation("吃飯");
        weekdayInformation.setStrTime("周一");
        weekdayInformation.setStrLocation("食堂");
        weekdayInformation.setStrClone(testClone);
        System.out.println(weekdayInformation.toString()); // 如果沒有重寫toString()方法會顯示:[email protected]

        WeekdayInformation week2=weekdayInformation.deepClone();// 這裡調用深克隆實作
        System.out.println("被引用對象是否相同:"+(weekdayInformation.getStrClone()==week2.getStrClone())); //相同? 不同 
        System.out.println("是否相同:"+(weekdayInformation.getStrInformation()==week2.getStrInformation())); //相同? 不同

        System.out.println(week2.toString());

        System.out.println("***********************");

        /*
         * weekdayInformation修改資訊 則week2的資訊也修改
         */
        TestClone testClone1=new TestClone();
        testClone1.setTestString("test1");

        System.out.println("weekdayInformation修改了資訊:");
        weekdayInformation.setStrTime("周二");
        weekdayInformation.setStrClone(testClone1); 
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());


        System.out.println("***********************");


        /*
         * week2修改資訊 則weekdayInformation的資訊也修改
         */
        TestClone testClone2=new TestClone();
        testClone2.setTestString("test2");
        System.out.println("week2修改了資訊:");
        week2.setStrTime("周三");
        week2.setStrClone(testClone2);  
        System.out.println(weekdayInformation.toString());
        System.out.println(week2.toString());

    }

}
/*      
輸出結果如下:

        事件:吃飯   時間:周一   地點:食堂   測試:test
        淺克隆
        克隆資訊如下:事件:吃飯    時間:周一   地點:食堂   測試:test

        克隆對象是否相同:false
        被引用對象TestClone是否相同:true
        基本對象String是否相同:true
        ***********

        事件:吃飯   時間:周一   地點:食堂   測試:test
        ***********************
        weekdayInformation修改了資訊:
        事件:吃飯   時間:周二   地點:食堂   測試:test1
        事件:吃飯   時間:周一   地點:食堂   測試:test
        ***********************
        week2修改了資訊:
        事件:吃飯   時間:周二   地點:食堂   測試:test1
        事件:吃飯   時間:周三   地點:食堂   測試:test2

*/




           

自我了解:

對象一 對象二=對象一的複制/淺克隆/深克隆

複制:對象一=對象二 二者完全值得同一個 如果對象一修改 對象二則跟着修改

淺克隆:對象一、二不同,但是對于被引用對象指向的會是同一個對象,

深克隆:對象一、二不同,是完全的建立出了一個新的對象,

對于被引用對象也不同,如這裡我所用到的引用對象testClone。

問題:

但是有個問題我沒搞懂,淺克隆的時候為什麼String類型的對象也指向的同一個?

也就是在例子三中

被引用對象TestClone是否相同:true //–這個應該是true

基本對象String是否相同:true //– 這個不應該是false嘛?怎麼回事true

源碼:

System.out.println("被引用對象TestClone是否相同:"+(weekdayInformation.getStrClone()==week2.getStrClone())); //相同?
System.out.println("基本對象String是否相同:"+(weekdayInformation.getStrInformation()==week2.getStrInformation())); //相同?
           

– 以上如果有錯,歡迎指出。