浅克隆、深克隆

// ----------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()); // ninthTestModel.WeekdayInformation@2a139a55
        
        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()); // ninthTestModel.WeekdayInformation@2a139a55
        
        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()方法显示: ninthTestModel.WeekdayInformation@2a139a55
        
    
        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()方法会显示:ninthTestModel.WeekdayInformation@2a139a55
        
        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())); //相同?

-- 以上如果有错,欢迎指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 说克隆之前,首先要说一下,js的数据类型 js中的数据类型分为两大类:原始类型和对象类型。 1)原始类型包括:数值...
    你期待的花开阅读 273评论 1 4
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,590评论 18 139
  • 307、setValue:forKey和setObject:forKey的区别是什么? 答:1, setObjec...
    AlanGe阅读 1,523评论 0 1
  • 1大同小异的工作周报 Sunny软件公司一直使用自行开发的一套OA (Office Automatic,办公自动化...
    justCode_阅读 1,145评论 0 3
  • Java 深克隆(DeepClone)与浅克隆(ShallowClone)是原型设计模式的灵魂。记录结构:--什么...
    markfork阅读 995评论 0 3