饿了么网站怎么做的,怎么建设推广网站,vr模式的网站建设公司,青海西宁网站建设公司1、概述
大家好#xff0c;我是欧阳方超。今天来看一下Java序列化与反序列化的问题。
2、序列化与反序列化
2.1、序列化与反序列化的概念
在Java中#xff0c;序列化是将对象转换为可存储或传输的格式#xff08;一般为字节流#xff09;的过程#xff0c;序列化后的字…1、概述
大家好我是欧阳方超。今天来看一下Java序列化与反序列化的问题。
2、序列化与反序列化
2.1、序列化与反序列化的概念
在Java中序列化是将对象转换为可存储或传输的格式一般为字节流的过程序列化后的字节流可以被传输给远程系统并在那里重新构造成原始对象。反序列化则是将序列化的数据转换回原始对象的过程反序列化是对象序列化的逆过程通过反序列化操作能够在接收端恢复出与发送端相同的对象。这是Java中的一种非常重要的机制可以将对象转换为字节流或其他格式以便在网络上传输或在磁盘上存储并在需要的时候进行恢复。
2.2、serialVersionUID出现的缘由
如果在序列化和反序列化前后类的结构发生了变化属性有增删会导致反序列化失败。 为了避免这种情况Java中引入了serialVersionUID这个机制用于标识序列化版本。当一个对象被序列化时会将这个对象的类的serialVersionUID的值写入到字节流中当一个对象被反序列化时JVM会从字节流中读取serialVersionUID的值并将其与反序列化对象所对应类的serialVersionUID值进行比较。如果这两个值不一致就会抛出InvalidClassException异常表示反序列化失败。我们用一个例子来验证一下
import java.io.*;public class TestMain {public static void main(String[] args) {Person person new Person(Jhon, 20);try {FileOutputStream fileOutputStream new FileOutputStream(D:\\home\\person.ser);ObjectOutputStream objectOutputStream new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(person);objectOutputStream.close();System.out.println(Serialized data is saved in person.ser);}catch (IOException e) {e.printStackTrace();}}
}class Person implements Serializable {private String name;private int age;public Person(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public int getAge() {return age;}
}上面的例子中创建了Person类的对象并经过序列化后保存到了磁盘上文件名为person.ser接下来我们为Person类额外添加一个属性address并试图从磁盘上的person.ser文件恢复出Person类的对象
import java.io.*;public class TestMain {public static void main(String[] args) {Person person null;//从文件中反序列化对象try {FileInputStream fileInputStream new FileInputStream(D:\\home\\person.ser);ObjectInputStream objectInputStream new ObjectInputStream(fileInputStream);person (Person)objectInputStream.readObject();System.out.println(person.getAge());System.out.println(person.getName());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}class Person implements Serializable {private String name;private int age;private String address;public Person(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public int getAge() {return age;}public String getAddress() {return address;}
}此时是会报错的
java.io.InvalidClassException: com.Person; local class incompatible: stream classdesc serialVersionUID -9177105843612582313, local class serialVersionUID 6433972014701326216at 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)报错的原因从上面的错误日志也可以看出是由于“stream classdesc serialVersionUID”与“local class serialVersionUID”导致的错误 。
为了避免这种情况Java中引入了serialVersionUID这个机制用于标识序列化版本。当一个对象被序列化时会将这个对象的类的serialVersionUID的值写入到字节流中当一个对象被反序列化时JVM会从字节流中读取serialVersionUID的值并将其与反序列化对象所对应类的serialVersionUID值进行比较。如果这两个值不一致就会抛出InvalidClassException异常表示反序列化失败。 如果一个类没有显式地定义serialVersionUID则在序列化时会根据类的结构自动生成一个但是这个自动生成的serialVersionUID值是不可控的。如果类的结构发生了变化可能会导致自动生成的serialVersionUID与旧版本不一致从而导致反序列化失败。为了避免这种情况我们应该显式地定义serialVersionUID以确保它的唯一性并在类结构发生变化时手动更新它以确保类的可序列化和反序列化的兼容性。 下面的示例中为Person类指定了serialVersionUID其值为1L注意通常我们使用随机数生成器或者手工定义一个值这样将Person类序列化到本地person.ser文件后不论怎么为Person类增删属性待验证的name和age属性就别删了总能恢复出创建Person对象时为name和age指定的值。
import java.io.*;public class TestMain {public static void main(String[] args) {Person person new Person(Jhon, 20);try {FileOutputStream fileOutputStream new FileOutputStream(D:\\home\\person.ser);ObjectOutputStream objectOutputStream new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(person);objectOutputStream.close();System.out.println(Serialized data is saved in person.ser);}catch (IOException e) {e.printStackTrace();}Person person1 null;//从文件中反序列化对象try {FileInputStream fileInputStream new FileInputStream(D:\\home\\person.ser);ObjectInputStream objectInputStream new ObjectInputStream(fileInputStream);person1 (Person)objectInputStream.readObject();System.out.println(person1.getAge());System.out.println(person1.getName());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}// 验证反序列化后的对象与原始对象是否一致System.out.println(Name: person1.getName());System.out.println(Age: person1.getAge());}
}class Person implements Serializable {private static final long serialVersionUID 1L;private String name;private int age;public Person(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public int getAge() {return age;}
}3、总结
所以为了避免反序列失败为序列化类新增属性时建议不要修改 serialVersionUID 字段的值当然如果完全不兼容升级避免反序列化混乱那么请修改 serialVersionUID 值。关于序列化和反序列化还有很多其他内容我们择日继续。 我是欧阳方超把事情做好了自然就有兴趣了如果你喜欢我的文章欢迎点赞、转发、评论加关注。下回见。