Java序列化和反序列化
什么叫序列化和反序列化?
序列化:对象转化为字节序列的过程叫做对象的序列化
反序列化:字节序列恢复为对象的过程叫做对象的反序列化
为啥要序列化?(序列化的用途)
-需要将对象永久的保存在硬盘中(比如Session对象)
-网络传输对象的序列(网络中的二进制序列)
过程:
序列化的过程:创建一个对象输出流对象,调用对象的writeObject()函数
反序列化的过程,创建一个对象输入流,调用readObject()函数
例子:
package Note; import java.io.*; /** * @author yintianhao * @createTime 20190218 21:46 * @description 序列化 */ public class People implements Serializable { //序列化id private static final long serialVersionUID = -5809782578272943999L; private int age; private String name; 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 static void main(String[] args) throws IOException,ClassNotFoundException { //序列化 People one = new People(); one.setAge(5); one.setName("张三"); ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(new File("G:/test.txt"))); stream.writeObject(one); stream.close(); //反序列化 ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt"))); People two = (People) stream1.readObject(); System.out.println("Name = "+two.getName()+"--age = "+two.getAge()); stream1.close(); } }
检验一下G盘是否有这个test.txt
再看Console
那么问题来了:serialVersionUID是干啥的?
看字面上的意思就是版本号嘛,那么这个版本号是干啥的呢
那么就有必要了解一下序列化的过程了:
序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
当然这里是我自己指定的serialVersionUID,如果这里我们不写也是没问题的,因为如果我们自己没定义serialVersionUID
jdk会自行给我们生成一个serialVersionUID,但是一般情况IDE会报个警告,不知道为啥IDEA没报,但是Eclipse是报了...
第一句是生成默认的版本ID,值为
第二句是根据类的类名信息等生成的,值为
但是如果我们不指定ID,那么,如果我们修改了类中的信息,比如增加或者删除某个属性,那么我们在反序列化之前的
对象的时候就会报错,因为这个修改后的类的serialVersionUID已经变了,所以不能反序列化第一次的对象
打个比方增加一个性别sex的选项,然后为了验证把之前的序列化的过程去掉,看改完后的这个能不能反序列化之前的
代码如下:
package Note; import java.io.*; /** * @author yintianhao * @createTime 20190218 21:46 * @description 序列化 */ public class People implements Serializable { //序列化id 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 static void main(String[] args) throws IOException,ClassNotFoundException { //反序列化 ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt"))); People two = (People) stream1.readObject(); System.out.println("Name = "+two.getName()+"--age = "+two.getAge()); stream1.close(); } }
运行,就报错了
Exception in thread "main" java.io.InvalidClassException: Note.People; local class incompatible: stream classdesc serialVersionUID = 8716394284034362776, local class serialVersionUID = 5389077117487999490
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at Note.People.main(People.java:37)
这里这个ID是由JDK的生成的,根据类的一些细节信息生成,具体怎么生成的我们不管,但是像刚才那样我们是不愿看见的,因为不同的Java编译器可能生成的
ID就不一样,所以还是强烈建议自定义一个明确的serialVersionUID
参考博客:https://www.cnblogs.com/xdp-gacl/p/3777987.html
https://www.cnblogs.com/duanxz/p/3511695.html