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

java对象流与序列化

2016-06-12 19:40 417 查看

对象序列化

Java语言有一种非常通用的对象序列化机制,它可以将任何对象写出到流中,并在之后将其读回。

序列化:把Java对象转换为字节序列的过程。
反序列化:把字节序列恢复为Java对象的过程。

具体实例:

我们先创建一个学生对象:

/*/
* 学生对象
*/
public class Student implements Serializable{
private String name;
private Integer age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Student(String name, Integer age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", address="
+ address + "]";
}

}

为了方便打印重写一下里面的toString()方法;
为了保存对象数据,首先需要打开一个objectOutputStream对象:

ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("C:\\E盘\\Student.java"));接着使用writeObject方法:
Student student=new Student("张三", 23, "111");
out.writeObject(student);

然后再读取我们的这个对象:
ObjectInputStream in=new ObjectInputStream(new FileInputStream("C:\\E盘\\Student.java"));
System.out.println(in.readObject());
这里要注意的是,在对象流中存储或恢复的所有类应进行修改,那么这些类必须实现Serializable接口;
实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。
序列化类的所有子类本身都是可序列化的。这个序列化接口没有任何方法和域,仅用于标识序列化的语意。允许非序列化类的子类型序列化,子类型可以假定负责保存和恢复父类型的公有的、保护的和(如果可访问)包的域的状态。只要该类(即父类)有一个无参构造子,可初始化它的状态,那么子类型就可承担上述职责;如果该类没有无参构造函数,在这种情况下申明一个可序列化的类是一个错误。此错误将在运行时被检测。

例如:Integer实现了Serializable,所以可以把一个Integer的对象用IO写到文件里,之后再可以从文件里读出,如你开始写入的时候那个对象的intValue() 是5的话,那读出来之后也是5。这一点体现了用序化类的作用,即用来传送类的对象。

特殊情况:

假如一个对象被多个对象共享,作为他们一部分时,会发生什么事情啦?

我们创建一个老师类:

public class Teacher implements Serializable{
private Student student;

public Student getStudent() {
return student;
}

public void setStudent(Student student) {
this.student = student;
}

public Teacher(Student student) {
super();
this.student = student;
}

@Override
public String toString() {
return "Teacher [student=" + student + "]";
}

}这里假设每个老师都有一个学生;
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("C:\\E盘\\teacher.java"));
Student student=new Student("张三", 23, "111");
Teacher teacher=new Teacher(student);
Teacher teacher2=new Teacher(student);
每个老师都包含一个学生对象的引用;在这里我们不能去保存和恢复学生对象的内存地址,因为当对象被重新加载时,它可能占据的是与原来完全不同的内存地址。
所以这里我们要为对象添加一个序列号保存;这种机制是对象序列化的原因所在,下面是其算法:

1.对你遇到的每一个对象引用都关联一个序列号;

2.对于每一个对象,当第一次遇到时,保存其对象数据到流中。

3.如果某个对象之前已经保存过,那么在写的时候,只会写出与之前保存过的序列号相同的对象;

4.对于流中的对象,在第一次遇到其序列号时,构建它,并使用流中数据来初始化它。然后记录这个序列号和新对象之间的关联;

5.当遇到与之前保存过的序列号的对象相同时,获取这个顺序号相关联的对象引用;

理解对象序列化的文件格式:

对象序列化是以特殊的文件格式存储对象数据的。比如 AC ED 后面紧跟着对象序列化格式的版本号00 05

当存储一个对象时,这个对象所属的类也必须存储。这个类的描述包含

1.类名。

2.序列化版本的唯一的ID serialVersionUID;

3.描述序列化方法的标志集。

4.对数据域的描述。

transient关键字:

如果我们不希望某些数据被序列化,可以使用transient关键字。他们会在对象序列化时被跳过;

当然与序列化有关的还有克隆复制方法,这个下次总结;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: