一、什么是对象的序列化和反序列化
序列化:把对象转换成字节序列的过程称为序列化
反序列化:把字节序列恢复成对象的过程称为反序列化
二、为什么要实现对象的序列化
1.把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中
2.在网络上传输数据,将对象以字节序列地方式进行传送
当需要存储大量对象(数十万个对象时,内存可能无法存储),这时就需要把对象进行序列化存储到硬盘中,等需要用的时候,再将硬盘中的对象还原到内存中进行使用。
当两个进程需要远程通信时,彼此可以发送各种类型的数据。虽然我们表面上看到的数据千奇百怪,表情、文字、符号等等,其实它们在网络上都是以二进制序列的形式进行传输的。发送方需要把这个java对象转换成字节序列,然后将二进制序列发送到网络上;此时,接受方收到消息,然后将二进制序列恢复为java对象。
三、如何实现序列化
3.1、使用JDK自带的API
java.io.ObjectOutputStream对象输出流,调用writeObject(Object obj)方法可以将obj对象进行序列化,把得到的字节序列写到一个目标输出流中。下面是以文件输出流为例子。
java.io.ObjectInputStream对象输入流,调用readObject(Object obj)方法从一个源输入流中读取字节序列,再把字节序列反序列为一个对象,并将对象返回。
实现了序列化接口的实体类:
public class Student implements Serializable{
private String id;
private String name;
private String sex;
private String grade;
//无参构造
public Student() {
}
//带参构造
public Student(String id, String name, String sex, String grade) {
this.id = id;
this.name = name;
this.sex = sex;
this.grade = grade;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", grade='" + grade + '\'' +
'}';
}
}
实现序列化和反序列化的工具类:
public class ObjSerializeAndDeserialize {
private static String filePath= Environment.getExternalStorageDirectory()+File.separator+"student.txt";
public static void SerializeStudent(Student student) throws FileNotFoundException,IOException{
//ObjectOutputStream对象输出流,将Student对象存储到E盘的student.txt中,从而实现序列化和存储
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File(filePath)));
//将对象进行写入
oos.writeObject(student);
oos.close();
}
public static Student DeserializeStudent() throws ClassNotFoundException, IOException{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(filePath));
Student student=(Student) ois.readObject();
ois.close();
return student;
}
}
运行结果:
序列化结果:
反序列化结果:
序列化Student成功后在存储目录中生成了一个student.txt文件,反序列化对象则是读取student.txt内容,并返回一个Student对象
3.2、使用第三方工具Gson
这个就比较简单了,直接使用Gson工具中的toJson(Object obj)方法,就可以将对象转化成jsonString字符串。
反序列化直接调用fromJson(String json),就可以得到之前的对象了。
四、serialVersionUID的作用
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量。在完成序列化后,java编译器会自动给这个class进行一个摘要算法,类似于指纹算法,只要文件发生任何改变,得到的UID就会不一样。那么可能由于我们对序列化对象的修改,比如增加某个属性,就会导致反序列化报错。
要解决这样的问题,serialVersionUID 就派上用场了,只要在javaBean对象中增加一个serialVersionUID 字段,用来标识这个类,而不是由编译器自动生成,这样当我们修改这个类时,反序列化就不会报错了。
private static final long serialVersionUID = 235412822564145941515L;