Java序列化反序化

网友投稿 724 2022-05-29

一、什么是序列化和反序列化

Java序列化就是指把Java对象转换为字节序列的过程

Java反序列化就是指把字节序列恢复为Java对象的过程。

二、为什么要把一个对象序列化

正常情况下,Java new出的对象,是保存在内存当中的,是不能持久化保存的,也不能直接在网络中传输,如何解决呢?就是把Java对象转换为byte字节数据,以字节的方式去实现持久化保存和网络传输。而反序列化,就是把须列化后的数据,重新恢复成内存中的Java对象。

总之,序列化,就是对一个Java对象的保存和重建的过程。

三、Java实现序列化的过程

Java序列化和反序化

为了让一个Java对象能序列化,我们需要为这个Java对象实现Serializable接口,像下面这样,这个方法和普通的Bean来说,多继承了这个接口,这个接口没有实现实现任何方法,它是为什么告诉编译器,这个接口可以序列化。

@Data public class User implements Serializable { private String name; private int age; private String sex; private String phone; }

这个类可以序列化了,但如何序列化让它能本地存储呢?执行下面的write方法,将会在D盘根目录下创建User类的序列化文件,执行read方法可以把序列化文件转变成对象。

public class Client { @Test public void write() throws Exception{ User user = new User(); user.setAge(15); user.setName("张三"); user.setPhone("123"); FileOutputStream fileOutputStream = new FileOutputStream("D://out.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(user); } @Test public void read() throws Exception{ FileInputStream fileInputStream = new FileInputStream("D://out.txt"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); User o = (User)objectInputStream.readObject(); System.out.println(o.toString()); } }

read方法运行结果,序列化出来的对象,拥有序列化之前对象的值。

四、不能被序列化的对象

Java对象中,如果一个字段被transient修饰,或者这个字段是static静态字段,这个类将不会被序列化,意味着,这个对象被序列化后,再次反序列化成Java对象后,对于的字段值为null。

五、序列号的作用

我们的类是不断的变动的,我们把一个对象序列化到本地文件后,有一天,这个对象的类发送了改变,我们用这个改变后的类接收序号化文件,会发生什么?把name和age注释掉,然后去反序列化。

public class User implements Serializable { // private String name; // // transient private int age; private String sex; private String phone; } public class Client { @Test public void write() throws Exception{ User user = new User(); // user.setAge(15); // user.setName("张三"); user.setPhone("123"); FileOutputStream fileOutputStream = new FileOutputStream("D://out.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(user); } @Test public void read() throws Exception{ FileInputStream fileInputStream = new FileInputStream("D://out.txt"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); User o = (User)objectInputStream.readObject(); System.out.println(o.toString()); } }

结果就是

java.io.InvalidClassException: com.example.service.demo01.User; local class incompatible: stream classdesc serialVersionUID = -118799779803260725, local class serialVersionUID = 1681826866445576943

这个报错是什么意思?是这个类和序列化文件里的类的序列号不一样,无法反序列化。

这里出现了一个问题,什么是序列号?

序列号是一个长整型的数据,一个类的序列号,是根据这个类的成员变量计算出来,如果成员变量发生改变,序列号也会发生改变,只有序列化文件的序列号和类的序列号相同,才能反序列化成功。

所以这个报错就很容易理解了,在改动前,类有三个变量,序列号的值假设是3,序列化的文件也是3,删除一个变量后,只剩两个变量,假设序列号是2,这样和序列化文件的序列号就不一样了,所以无法反序列化。

有时候,我们希望,即使类发生了改变,也能反序列化成功,比如之前有现在只剩3个字段,序列化的文件有4个字段,我们只序列化现在的类有的字段,那该怎么做?

我们可以手动为一个类设置序列号,像这样:

这样,即使类发生了改变,但是序列号我们已经手动写死了,之后类再怎么发生变化,反序列化也不会报错,只会序列那化些还能对应上的值。

Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:2021年上半年总结
下一篇:CPU知识
相关文章