1、什么是序列化和反序列化
序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。
反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。
2、为什么需要序列化与反序列化
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。其实序列化的目的就是跨进程传递格式化数据
3、如何实现序列化与发序列化
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。然后j通过ObjectOutputStream的writeObject方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。通过jObjectInputStream的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。那我们先写个Demo,代码如下:
public class Student implements Serializable {
private static final long serialVersionUID =1l;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
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 class TestSerializeAndDeserialize {
public static void main(String[] args) throws Exception {
SerializePerson();
Student stu=DeserializePerson();
System.out.println(stu.getName()+" "+stu.getSex()+" "+stu.getAge());
}
private static void SerializePerson() throws IOException {
Student stu=new Student();
stu.setAge(10);
stu.setName("xiaoming");
stu.setSex("man");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:/Student.txt")));
oos.writeObject(stu);
System.out.println("Student对象序列化成功");
oos.close();
}
private static Student DeserializePerson()throws Exception,IOException{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:/Student.txt")));
Student stu=(Student)ois.readObject();
System.out.println("Student对象反序列化成功");
return stu;
}
}
程序运行结果:
4.serialVersionUID的作用
serialVersionUID: 序列化的版本号,凡是实现Serializable接口的类都应有一个表示序列化版本标识符的静态变量。如果没有serialVersionUID会怎么样,我们去掉serialVersionUID后再运行程序结果如下:
下面我们在Student类新添一个score属性,如下:
然后执行反序列操作,此时就会抛出如下的异常信息:
Exception in thread "main" java.io.InvalidClassException: com.lg.match.Student;
local class incompatible: stream classdesc serialVersionUID = -379872992605699466,
local class serialVersionUID = 8365482709425766029
如果添加serialVersionUID,再执行上面操作,运行结果如下:
serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。
显式地定义serialVersionUID有两种用途:
1、 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
2、 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。