一.什么是序列化与反序列化
1.序列化:把对象转换为字节序列的过程称为对象的序列化
2.反序列化:把字节序列转换为对象的过程称为对象的反序列化
有时候要将信息持久化保存起来,序列化的意思就是将内存里的对象变成一连串的字节描述的过程,常见的就是变成文件。
二.什么时候需要序列化
1.把内存中的对象状态保存到一个文件或者数据库中的时候
2.用套接字在网络上传送对象的时候
三.如何实现序列化(Java对象序列化)
自己实现一个person类,定义一些变量,如果要对Person进行序列化需要实现Serializable接口
代码示例1:
package com.io;
import java.io.*;
class Person implements Serializable {
//private static final long serialVersionUID=1L;
private String name;
private int age;
private String sex;
//被transient修饰的变量,不能被序列化
transient private int stuId;
//static修饰的变量不能被序列化
private static int count=99;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getStuId() {
return stuId;
}
public void setStuId(int stuId) {
this.stuId = stuId;
}
@Override
public String toString() {
return "Serializable{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", stuId=" + stuId +
", count=" + count +
'}';
}
}
//测试类
public class TestDemo{
public static void main(String[] args) throws Exception{
serializePerson();
Person person=deserializePerson();
System.out.println(person.toString());
}
//序列化操作
public static void serializePerson() throws IOException{
Person person=new Person();
person.setName("dudu");
person.setAge(12);
person.setSex("女");
person.setStuId(199);
//ObjectOutputStream对象输出流,将person对象存储到指定路径下
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:\\icons\\person.txt")));
oos.writeObject(person);
System.out.println("person序列化成功!");
oos.close();
}
//反序列化操作
public static Person deserializePerson() throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:\\icons\\person.txt")));
Person person=(Person)ois.readObject();
System.out.println("person对象反序列化成功!");
ois.close();
return person;
}
}
关于ObjectOutputStream说明: 他代表对象输出流,它的writeObject(Object obj)方法可以对参数指定的对象进行序列化,把得到的字节序列写到一个目标输出流中。
关于ObjectInputStream说明: 他代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
运行结果:
运行结果分析:
1.首先实现了对象的序列化和反序列化
2.triansient修饰的属性,不会被序列化。上述stuId值为0,内置类型对应值为0,引用类型对应值为null
3.静态变量在上述结果中看着好像被序列化了,其实并没有
四.关于静态变量数据属性是否被初始化测试
将上述代码的主函数修改为如下形式,即不进行序列化,直接进行反序列化,然后将count的值修改为111
public static void main(String[] args) throws Exception{
//serializePerson();
Person person=deserializePerson();
System.out.println(person);
}
运行结果:
观察发现count的值改为111,代码并没有进行序列化,也就是说person.txt中的count的值应该还是上次序列化之后的99,由此可知静态变量是不会被进行序列化的
五.关于serialVersionUID的问题
将代码示例1中第一行private static final long serialVersionUID=1L;的注释取消掉,再将主函数中序列化操作serializePerson()屏蔽掉,运行代码,此时出现异常。
当类中没有指定serialVersionUID时,编译器会自动赋值,,如果序列化是以默认的serialVersionUID,那么反序列化也是会以默认的。而在上述代码屏蔽了序列化之后就代表以默认的serialVersionUID进行序列化,以自己赋值的serialVersionUID进行反序列化,这样就会出现问题。所以在实现Serializable接口的时候,一定要给serialVersionUID赋值。不同的serialVersionUID值,会影响到反序列化。