一.序列化特征
1.序列化之前的对象通常是瞬时的,动态的,可变的;序列化之后的结果通常是持久的,静态的,不可变的。
2.序列化的目的通常是为了使得对象得以保存,或者传输。
3.序列化过程通常有反序列化过程与之对应。
二.Java Serializable
将Java 对象的元数据及其状态保存为二进制数组。在必要的时候可以通过解析该二进制数组,重新生成该对象并恢复其状态。这里着重说明一下什么是对象的状态。对象的状态实际上就是其成员变量的值,因此保存对象状态就是保存其对象的值。
实现了一种对象状态的保存和恢复方法。
实现了一种方法或者过程的远程调用方法。
三.关于serialVersionUID
序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
有两种生成方式:
一个是默认的1L,比如:
private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = 3688326153694834789L;
四.实现java.io.Serializable 接口
参见JDK文档
简单测试代码
package com.my.model;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 3688326153694834789L;
private String name;
private int age;
public User(){
}
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
package com.my.util;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import com.my.model.User;
public class SerializableToFile {
public static void main(String[] args) {
SerializableToFile stf = new SerializableToFile();
stf.save();
stf.resove();
}
public void save() {
User[] user = new User[3];
user[0] = new User("Tom7", 17);
user[1] = new User("Tom8", 18);
user[2] = new User("Tom9", 19);
try {
FileOutputStream fos = new FileOutputStream("D:\\My Documents\\Downloads\\User.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
for (int i = 0; i < user.length; i++) {
System.out.println("<save>User name: " + user[i].getName());
System.out.println("<save>User Age: " + user[i].getAge());
}
oos.writeObject(user);
oos.flush();
oos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void resove() {
try {
FileInputStream fis = new FileInputStream("D:\\My Documents\\Downloads\\User.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
/*
* String name = (String)ois.readObject(); int age = ois.readInt();
*/
try {
User[] user = (User[]) ois.readObject();
if (user != null) {
for (int i = 0; i < user.length; i++) {
System.out.println("<resove>User name: " + user[i].getName());
System.out.println("<resove>User Age: " + user[i].getAge());
}
}
} catch (EOFException e) {
// TODO: handle exception
System.out.println("Read file Done!");
}
ois.close();
} catch (Exception e) {
/*
* if(e instanceof EOFException){
*
* }
*/
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
<save>User name: Tom7
<save>User Age: 17
<save>User name: Tom8
<save>User Age: 18
<save>User name: Tom9
<save>User Age: 19
<resove>User name: Tom7
<resove>User Age: 17
<resove>User name: Tom8
<resove>User Age: 18
<resove>User name: Tom9
<resove>User Age: 19
代码执行时遇到的异常:
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
需要捕捉EOFException
while (user != null)
结果为死循环 改成
if (user != null)
参考文章:
Java深度历险(十)——Java对象序列化与RMI
JAVA中SERIALVERSIONUID的解释
Java序列化之一: 什么是JAVA序列化
Java序列化的机制和原理,以及自定义序列化问题