您的位置:首页 > 编程语言 > Java开发

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

2015-08-27 11:05 423 查看
关于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,这个值需要我们令行设置
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: