这两天在看有关序列化与反序列化的内容,大概知道了序列化与反序列化的作用,特此记录下,记录的同时 希望对迷惑这一块内容的同学有所帮助 。另外参考文章如下,讲的很仔细。原文地址
序列化与反序列化的概念
- 序列化:将对象序列化为字节序列的过程称为序列化.
- 反序列化:将字节序列转换为反序列化对象的过程称为反序列化
- Serializable接口:没有任何抽象方法需要实现,只要对象实现了这个接口,就可以对该对象进行序列化与反序列化操作.如果没有指明serialVersionUID,那么编译器在将java文件加载为class字节码的过程中会默认添加一个随机serialVersionUID属性.
序列化与反序列化的作用
序列化与反序列化一般有2个作用:
- 数据持久化:简而言之就是将数据存储到磁盘文件的时候,需要将对象序列化存入磁盘中. 举个最常用的例子:Tomcat中存储session信息,当10W个人同时访问Web服务器,需要将10W个session同时存入tomcat内存中,但是tomcat的内容是有限制的,那么如何解决这一问题那?就是通过将一些不活动但是未超过生命周期的sesssion序列化存储到磁盘中,当需要用到的时候反序列化读取出来。
- 网络传输中:当分布式系统中需要传输同一个对象时,就用到序列化与反序列化。将传输的对象序列化 传输到另一个系统中,另一个系统读取的时候通过将字节序列转换为对象读取出来.
serialVersionUID的作用
- serialVersionUID的作用就是保证了序列化与反序列保证了 对象属性发生了改变不影响序列化与反序列的进行。比如讲
将一个Customer对象实现了Serializable接口,如果不声明serialVersionUID属性,序列化该对象
会默认生成一个serialVersionUID,然后向该对象中添加一个新的code属性,在将磁盘中的字节序列读取出来的时候,就会因为新的Customer对象中默认生成的serialVersionUID与磁盘中的字节序列serialVersionUID不一致而导致反序列胡失败。解决办法就是添加一个常量serialVersionUID,这样不由编译器生成serialVersionUID,那么serialVersionUID也就不会改变。那么不论对象怎么改,反序列化都没有问题.
java.io.InvalidClassException: serialiable.Customer; local class incompatible: stream classdesc serialVersionUID = 2918975353393695766, local class serialVersionUID = -2999019177624378121
正确序列化的方式
Person.java
package serialiable;
import java.io.Serializable;
public class Person implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public Person(int age, String name, String sex) {
super();
this.age = age;
this.name = name;
this.sex = sex;
}
private int age;
private String name;
private String sex;
private String xx;
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 String toString() {
return "Person [age=" + age + ", name=" + name + ", sex=" + sex + "]";
}
}
CurrentDemo.java
package serialiable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class CurrentDemo {
@SuppressWarnings("resource")
public static void main(String[] args) {
try {
/**
* 1.通过ObjectOutputStream的成员方法writer将对象经过序列化存入到磁盘中
* 2.通过ObjectInputStream.readObject方法将字节序列 反序列化,读取对象信息
*/
/*Person person = new Person(22, "张三", "男");
FileOutputStream fileOutputStream = new FileOutputStream(new File("C:\\Person.txt"));
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(person);
System.out.println("对象序列化成功");
FileInputStream fileInputStream = new FileInputStream(new File("C:\\Person.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Person person2 = (Person) objectInputStream.readObject();
System.out.println(person2);
System.out.println("磁盘对象反序列化成功");*/
/*
* 读取反序列化的对象
*/
FileInputStream fileInputStream = new FileInputStream(new File("C:\\Person.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Person person2 = (Person) objectInputStream.readObject();
System.out.println(person2);
System.out.println("磁盘对象反序列化成功");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
没有声明serialVersionUID的错误例子
Customer.java
package serialiable;
import java.io.Serializable;
public class Customer implements Serializable{
public Customer(int age, String name, String sex) {
super();
this.age = age;
this.name = name;
this.sex = sex;
}
private int age;
private String name;
private String sex;
private String xx;
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 String toString() {
return "Person [age=" + age + ", name=" + name + ", sex=" + sex + "]";
}
}
FailureDemo.java
package serialiable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class FailureDemo {
public static void main(String[] args) {
try {
/**
* 1.通过ObjectOutputStream的成员方法writer将对象经过序列化存入到磁盘中
* 2.通过ObjectInputStream.readObject方法将字节序列 反序列化,读取对象信息
*/
/*Customer customer = new Customer(22, "张三", "男");
FileOutputStream fileOutputStream = new FileOutputStream(new File("C:\\Customer.txt"));
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(customer);
System.out.println("对象序列化成功");
FileInputStream fileInputStream = new FileInputStream(new File("C:\\Customer.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Customer customer2 = (Customer) objectInputStream.readObject();
System.out.println(customer2);
System.out.println("磁盘对象反序列化成功");*/
/*
* 读取反序列化的对象
*/
FileInputStream fileInputStream = new FileInputStream(new File("C:\\Customer.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Customer customer2 = (Customer) objectInputStream.readObject();
System.out.println(customer2);
System.out.println("磁盘对象反序列化成功");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
总结
序列化作为数据持久化的一个重要知识点,竟然到现在才了解。羞愧不已,与同行的人差距也越来越大,加油!