作用
对象序列化主要是将java对象保存到磁盘中,或者允许在网络中直接传递对象数据。通常建议,程序创建的每一个javabean都可以进行序列化。
如何序列化
1、Serializable接口(通常只用这种)
2、Extmalizable
序列化原则
1、Serializable仅仅是一个标示性接口,接口中没有任何的方法和字段,仅用于标示序列化。
2、javaBean中静态变量和成员方法不可以序列化。
3、如果对象的属性是对象,属性对应类也必须实现Serializable接口
4、对象序列化之后,写入的是一个二进制文件,所以存在乱码是正常现象。
如何实现序列化
• 创建ObjectOutputStream对象
• 调用writeObject()输出对象
OutputStream fos = new FileOutputStream(new File("d:/java6.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(stu);
oos.close();
如何实现反序列化
• 创建ObjectInputStream对象
• 调用readObject()读取对象
InputStream fis = new FileInputStream(new File("d:/java6.txt"));
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu = (Student)ois.readObject();
System.out.println(stu.getAge()+" "+stu.getScore());
多对象的反序列化
FileInputStream fos = new FileInputStream("F:\\edu\\javaSE\\IO\\temp\\student.txt");
ObjectInputStream ois = new ObjectInputStream(fos);
while (fos.available() > 0) {
StudentVO stu = (StudentVO)ois.readObject();
System.out.println(stu.getId()+" "+stu.getName()+" "+stu.getAge());
}
ois.close();
对象应用的序列化
问题:
统一对对象,会被多次序列化
解决:
- 所有保存到磁盘中的java对象,都有一个序列化的编号(serialVersionUID)
- 当程序要序列化某个对象时,会先检查对象是否序列化过,只有对象没有序列化过(本次虚拟机JVM中)才会被序列化
- 如果对象已经被序列化过,程序将直接输出一个序列化编号,而不是重新序列化。
serialVersionUID
方式:
- 1L
- 根据属性和方法计算出来的
4507342025885372190L
解决多次序列化读取问题
1、继承ObjectOutputStream类,并重写writeStreamHeader方法
2、再非第一次序列化操纵时,使用重写后的writeStreamHeader方法
public class MyObjectOutputStream extends ObjectOutputStream{
public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
public void writeStreamHeader() throws IOException {
System.out.println("MyObjectOutputStream writeStreamHeader");
return;
}
}
ObjectOutputStream oos = null;
if (file.length() > 0) {//说明文件中已经存在序列化过的数据(不是第一次)
oos = new MyObjectOutputStream(fos);
} else {//说明文件还没有写入序列化的内容
oos = new ObjectOutputStream(fos);
}
transient
被此关键字修饰的属性,不能被序列化
自定义序列化
在需要自定序列化的对象里面分别重写writeObject,readObject方法
/**
* 自定义序列化
* @param out
* @throws IOException
*/
private void writeObject(ObjectOutputStream out) throws IOException {
System.out.println("自定义序列化");
out.writeObject(names);
out.writeInt(age);
out.writeObject(password);
}
/**
* 自定反义序列化
* @param out
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("自定反义序列化");
this.names = (String) in.readObject();
this.age = in.readInt();
this.password = (String) in.readObject();
}