概念
通过序列化和反序列化实现实例的交互,比如RPC、分布式缓存读写。
如果不这么做,只能在消息中传值,交互太简单
原理
序列化时将源文件的类型定义和数据转换为字节码文件,反序列化时将字节码转换为源文件和数据
使用
序列化需要类实现Java.io.serilizable接口,所有成员都必须可序列化,如果有类成员变量也必须是可序列化。
序列化时默认生成xx.ser文件。
序列化
- 声明文件输出流到一个ser文件,
- 由此创建对象输出流,
- 然后调用writeObject方法序列化
反序列化
- 创建ser文件的输入流
- 由此创建对象输入流
- 调用readObject方法得到反序列化的对象引用
import java.util.*;
import java.io.*;
public class SerilizeTest implements Serializable{
public String name;
public transient int SSN;
public void mailBack(){
System.out.println(name);
}
public static void main(String[] args){
SerilizeTest test = new SerilizeTest();
test.name="Chris";
test.SSN=2;
String filePath = "D:/SerilizeTest.ser";
try{
FileOutputStream fileOut =
new FileOutputStream(filePath);
ObjectOutputStream obOut =
new ObjectOutputStream(fileOut);
obOut.writeObject(test);
obOut.close();
fileOut.close();
System.out.println("object is saved in D:/SerilizeTest.ser");
}catch(IOException e){
e.printStackTrace();
}
SerilizeTest deSer=null;
try{
FileInputStream fileIn=
new FileInputStream(filePath);
ObjectInputStream obIn=
new ObjectInputStream(fileIn);
deSer = (SerilizeTest) obIn.readObject();
System.out.println("The object is deSered");
System.out.println("name is"+deSer.name);
System.out.println("SSN is"+deSer.SSN);
}catch(IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
延伸
- 关于serialVersionUID最好显式定义,表明类的版本,即根据类型和成员变量生成一个64位Hash值
反序列化时就可以根据这个id校验类版本
避免采用默认UID即1L时,由于编译器不同,产生的UID不同而无法反序列化 - 显式定义的好处还有,当修改类定义时,旧的实例能正常反序列化,因为新增或变更的字段的值会变为默认值。如果采用默认UID,反序列化旧的实例就会因为UID不一致而出错