Java串行化深度复制与性能调优

来源:互联网 发布:windows有王者荣耀吗 编辑:程序博客网 时间:2024/05/24 00:28

关于java的浅度复制与深度复制的概念大家可以在许多博文中找到

我们直接上代码,看一下浅度复制的一个例子:

这里有三个类College,Teacher,Student

College类

public class College {    private String name;        public College(){            }        public College(String name) {        super();        this.name = name;    }    //setter/getter    ...}
Teacher类
public class Teacher {    private String name;    private Integer age;    private College college;    private List<Student> students;        public Teacher() {    }        public Teacher(String name, Integer age) {        super();        this.name = name;        this.age = age;    }    //setter/getter    ...}

Student类

public class Student {    private String name;    private Integer age;    private String className;        public Student() {    }        public Student(String name, Integer age, String className) {        super();        this.name = name;        this.age = age;        this.className = className;    }    //setter/getter    ...}

测试类

public class TestClone {    @Test    public void testShallowClone() {        College college1 = new College("ACollege");        Teacher teacher1 = new Teacher("ATeacher", 32);        Student student1 = new Student("AStudent1", 14, "1-A");        Student student2 = new Student("AStudent2", 15, "1-A");        List<Student> students = Arrays.asList(student1,student2);        teacher1.setCollege(college1);        teacher1.setStudents(students);                //浅度复制一个例子,这里可以用Colne()代替        Teacher teacher2 = new Teacher(teacher1.getName(),teacher1.getAge());        teacher2.setCollege(teacher1.getCollege());        teacher2.setStudents(teacher1.getStudents());                System.out.println(teacher1);        System.out.println(teacher2);        System.out.println(teacher1.getCollege());        System.out.println(teacher2.getCollege());    }}

运行结果为

com.clone.Teacher@238e0d81
com.clone.Teacher@31221be2
com.clone.College@377dca04
com.clone.College@377dca04

简单学过java的人都应该知道这个结果,这就时浅度复制的一个例子,它只能复制一个对象,这两个对象只是内存地址不同,其他的都相同,包括引用类型的属性,他们都指向同一个引用。用一下对象图表示


然而如果我们要得到以下效果该如何呢




这里提供一个串行化的解决方案

关于什么时串行化(序列化)与反串行化(反序列化)这里不再敖述。

需要对类作如下修改

College类

public class College implements Serializable{    private static final long serialVersionUID = 1590896985634442223L;    private String name;        public College(){            }        public College(String name) {        super();        this.name = name;    }    //setter/getter   ...}Teacher类
public class Teacher {    private static final long serialVersionUID = -5667751032495765380L;    private String name;    private Integer age;    private College college;    private List<Student> students;        public Teacher() {    }        public Teacher(String name, Integer age) {        super();        this.name = name;        this.age = age;    }    //setter/getter    ...}Student类
public class Student implements Serializable {        private static final long serialVersionUID = -4445065573351962915L;    private String name;    private Integer age;    private String className;        public Student() {    }        public Student(String name, Integer age, String className) {        super();        this.name = name;        this.age = age;        this.className = className;    }    //setter/getter    ...}
进行深度复制的代码需要进行将对象转化为字节流与将字节流转化为对象的操作:
@Test    public void testDeepClone() {        College college1 = new College("ACollege");        Teacher teacher1 = new Teacher("ATeacher", 32);        Student student1 = new Student("AStudent1", 14, "1-A");        Student student2 = new Student("AStudent2", 15, "1-A");        List<Student> students = Arrays.asList(student1,student2);        teacher1.setCollege(college1);        teacher1.setStudents(students);        //将对象转化为字节流        ByteArrayOutputStream baos = null;        ObjectOutputStream oos = null;        ByteArrayInputStream bais = null;        ObjectInputStream ois = null;        try {            baos = new ByteArrayOutputStream();            oos = new ObjectOutputStream(baos);            oos.writeObject(teacher1);            byte []buf = baos.toByteArray();            bais = new ByteArrayInputStream(buf);            ois = new ObjectInputStream(bais);            Teacher teacher2 = (Teacher) ois.readObject();            System.out.println(teacher1);            System.out.println(teacher2);            System.out.println(teacher1.getCollege());            System.out.println(teacher2.getCollege());        } catch (Exception e) {            e.printStackTrace();        } finally {            if (ois != null) {                try {                    ois.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if (bais != null) {                try {                    bais.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }                        if (oos != null) {                try {                    oos.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }                        if(baos != null) {                try {                    baos.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    }

得出的结果为

com.clone.Teacher@246b179d
com.clone.Teacher@6e5e91e4
com.clone.College@b81eda8
com.clone.College@2cdf8d8a

这样就达到深度复制的效果了


在测试中我们会发现这样一个问题,如果在College没有实现Serializable接口,在进行深度复制时会报一个这样的一个异常:java.io.NotSerializableException,所在对象未序列化异常

可以想象以下,如果College里有一个List<Teacher>对象,那么在保证teacher1正常复制的情况下,会序列化一个庞大的对象网络,

一个学校有多名老师,一个老师有多名学生。。。为了达到复制一个老师信息的效果,结果把整个学校的信息全序列化了,这样时非常糟糕的,而且没有必要,十分浪费资源且性能太低。这时候我们就需要用到关键字transient,临时的。使用transient关键子修饰的对象将不再维护序列化机制,最后复制下来的时students,而college将会使null,这个值需要我们令行设置

0 0
原创粉丝点击