Java串行化深度复制与性能调优
2015-08-27 11:05
423 查看
关于java的浅度复制与深度复制的概念大家可以在许多博文中找到
我们直接上代码,看一下浅度复制的一个例子:
这里有三个类College,Teacher,Student
College类
Student类
测试类
运行结果为
com.clone.Teacher@238e0d81
com.clone.Teacher@31221be2
com.clone.College@377dca04
com.clone.College@377dca04
简单学过java的人都应该知道这个结果,这就时浅度复制的一个例子,它只能复制一个对象,这两个对象只是内存地址不同,其他的都相同,包括引用类型的属性,他们都指向同一个引用。用一下对象图表示
然而如果我们要得到以下效果该如何呢
这里提供一个串行化的解决方案
关于什么时串行化(序列化)与反串行化(反序列化)这里不再敖述。
需要对类作如下修改
College类
得出的结果为
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,这个值需要我们令行设置
我们直接上代码,看一下浅度复制的一个例子:
这里有三个类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,这个值需要我们令行设置
相关文章推荐
- Java 单例模式
- Eclipse:The project cannot be built until build path errors are resolved
- 嵌套类
- 转:对java中int与Integer的一些理解
- eclipse Android 运行总是debug模式
- 删除eclipse中不用的svn地址
- JAVA问题总结之15-多个类之间的调用
- 异常——Caused by: java.sql.SQLException: ORA-00911: 无效字符
- spring 中InitializingBean, DisposableBean
- java 编程思想之7.2.1初始化基类
- Java判断浏览器类型
- Java基础知识强化01:short s = 1; s = s + 1;与short s = 1; s += 1;
- 个人环境搭建——搭建JDK环境
- HBase之Java API实操
- 基于restful风格的maven项目实践(融合spring)
- Quartz集成Spring框架
- 关于javax.servlet不存在的问题
- leetcode--PalindromeLinkedList
- javaweb学习总结(二十八)——JSTL标签库之核心标签
- JAVA设置session超时失效的方式