Java中的深拷贝与浅拷贝ArrayList

来源:互联网 发布:windows 系统调试模式 编辑:程序博客网 时间:2024/04/29 15:45

今天研究了一下深拷贝和浅拷贝的问题,以前一直有点迷糊。

首先新建TestObj类

public class TestObj implements Serializable{    private String str1;    private String str2;    private int int2;    public TestObj(String str1, String str2, int int2) {        this.str1 = str1;        this.str2 = str2;        this.int2 = int2;    }    public String getStr1() {        return str1;    }    public void setStr1(String str1) {        this.str1 = str1;    }    public String getStr2() {        return str2;    }    public void setStr2(String str2) {        this.str2 = str2;    }    public int getInt2() {        return int2;    }    public void setInt2(int int2) {        this.int2 = int2;    }    @Override    public String toString(){       return "[str1:"+this.str1+",str2:"+this.str2+",int2:"+int2+"]";    }}

新建TestList类:

import java.io.*;import java.util.ArrayList;public class TestList<TestObj> extends ArrayList<TestObj> {    private String strField;    private TestObj objField;    public String getStrField() {        return strField;    }    public void setStrField(String strField) {        this.strField = strField;    }    public TestObj getObjField() {        return objField;    }    public void setObjField(TestObj objField) {        this.objField = objField;    }    @Override    public String toString(){        StringBuilder accum = new StringBuilder("TestList[");        accum.append("strField:").append(this.strField).append(",objField:").append(objField);        accum.append("{");        for(TestObj obj : this){           accum.append(obj).append(",");        }        accum.append("}]");        return accum.toString();    }}

编写测试用例:TestCase

import java.io.IOException;public class TestCase {    public static void main(String[] args) throws IOException, ClassNotFoundException {        TestList<TestObj> list = new TestList<TestObj>();        TestObj obj1 = new TestObj("字符串1","字符串2",1);        list.add(obj1);        TestObj obj2 = new TestObj("字符串3","字符串4",2);        list.add(obj2);        list.setStrField("原有域");        TestObj objj = new TestObj("原有域str1","原有域str2",3);        list.setObjField(objj);        TestList<TestObj> cloneList = (TestList<TestObj>) list.clone();        System.out.println("原有对象:"+list);        cloneList.setStrField("修改后域");        cloneList.get(0).setStr1("修改后字符串1");        cloneList.get(0).setStr2("修改后字符串2");        cloneList.getObjField().setStr1("修改后域str1");        cloneList.getObjField().setStr2("修改后域str2");        cloneList.getObjField().setInt2(111);        System.out.println("修改后Clone对象:"+cloneList);        System.out.println("修改后原有对象:"+list);    }}

运行结果:

原有对象:TestList[strField:原有域,objField:[str1:原有域str1,str2:原有域str2,int2:3]{[str1:字符串1,str2:字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]
修改后Clone对象:TestList[strField:修改后域,objField:[str1:修改后域str1,str2:修改后域str2,int2:111]{[str1:修改后字符串1,str2:修改后字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]
修改后原有对象:TestList[strField:原有域,objField:[str1:修改后域str1,str2:修改后域str2,int2:111]{[str1:修改后字符串1,str2:修改后字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]

比对可发现TestList的String域值clone成功,修改Clone对象原对象简单域无变化;但是Object域以及List内容都只是引用,修改Clone对象后,原对象跟着变化。

这是浅拷贝的问题。

如何由浅入深呢

方法一:

首先TestObj需要实现Serializable接口

TestList添加deepClone方法:

public TestList<TestObj> deepClone() throws IOException, ClassNotFoundException{        TestList<TestObj> dest =null;        ByteArrayOutputStream byteOut = null;        ObjectOutputStream out = null;        ByteArrayInputStream byteIn = null;        ObjectInputStream in = null;        try{            byteOut = new ByteArrayOutputStream();            out =  new ObjectOutputStream(byteOut);            out.writeObject(this);
            byteIn = new ByteArrayInputStream(byteOut.toByteArray());            in  =new ObjectInputStream(byteIn);            dest =  (TestList<TestObj>)in.readObject();        }finally{              if(byteOut!=null){                  byteOut.close();              }               if(out!=null){                   out.close();               }              if(byteIn!=null){                  byteIn.close();              }              if(in!=null){                  in.close();              }        }        return dest;    }

修改测试用例中的clone为deepClone();

import test.simple8583.TestList;import test.simple8583.TestObj;import java.io.IOException;public class TestCase {    public static void main(String[] args) throws IOException, ClassNotFoundException {        TestList<TestObj> list = new TestList<TestObj>();        TestObj obj1 = new TestObj("字符串1","字符串2",1);        list.add(obj1);        TestObj obj2 = new TestObj("字符串3","字符串4",2);        list.add(obj2);        list.setStrField("原有域");        TestObj objj = new TestObj("原有域str1","原有域str2",3);        list.setObjField(objj);        TestList<TestObj> cloneList = list.deepClone();        System.out.println("原有对象:"+list);        cloneList.setStrField("修改后域");        cloneList.get(0).setStr1("修改后字符串1");        cloneList.get(0).setStr2("修改后字符串2");        cloneList.getObjField().setStr1("修改后域str1");        cloneList.getObjField().setStr2("修改后域str2");        cloneList.getObjField().setInt2(111);        System.out.println("修改后Clone对象:"+cloneList);        System.out.println("修改后原有对象:"+list);    }}

执行结果:
原有对象:TestList[strField:原有域,objField:[str1:原有域str1,str2:原有域str2,int2:3]{[str1:字符串1,str2:字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]
修改后Clone对象:TestList[strField:修改后域,objField:[str1:修改后域str1,str2:修改后域str2,int2:111]{[str1:修改后字符串1,str2:修改后字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]
修改后原有对象:TestList[strField:原有域,objField:[str1:原有域str1,str2:原有域str2,int2:3]{[str1:字符串1,str2:字符串2,int2:1],[str1:字符串3,str2:字符串4,int2:2],}]

测试结果显示clone对象变更,原对象无变化。TestList已实现深度拷贝。





0 0
原创粉丝点击