serialVersionUID的用途是什么
原文: https://javabeginnerstutorial.com/core-java-tutorial/use-serialversionuid/
在这里,我将讨论在可序列化类中使用的变量serialVersionUID的重要性。
下面是一个使您了解变量的确切用法的示例。
示例代码
Employee.java
package com.jbt;import java.io.Serializable;public class Employee implements Serializable{public String firstName;public String lastName;private static final long serialVersionUID = 5462223600l;}
SerializaitonClass.java(此类将用于序列化)
package com.jbt;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;public class SerializaitonClass {public static void main(String[] args) {Employee emp = new Employee();emp.firstName = "Vivekanand";emp.lastName = "Gautam";try {FileOutputStream fileOut = new FileOutputStream("./employee.txt");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(emp);out.close();fileOut.close();System.out.printf("Serialized data is saved in ./employee.txt file");} catch (IOException i) {i.printStackTrace();}}}
DeserializationClass.java(此类将用于反序列化)
package com.jbt;import java.io.*;public class DeserializationClass {public static void main(String[] args) {Employee emp = null;try {FileInputStream fileIn = new FileInputStream("./employee.txt");ObjectInputStream in = new ObjectInputStream(fileIn);emp = (Employee) in.readObject();in.close();fileIn.close();} catch (IOException i) {i.printStackTrace();return;} catch (ClassNotFoundException c) {System.out.println("Employee class not found");c.printStackTrace();return;}System.out.println("Deserializing Employee...");System.out.println("First Name of Employee: " + emp.firstName);System.out.println("Last Name of Employee: " + emp.lastName);}}
现在执行“SerializationClass.java”,然后执行“DeserializationClass.java”。 它将首先创建一个具有Employee对象状态的文件,然后在反序列化时从同一文件创建一个对象。 输出将如下所示。
Serialized data is saved in ./employee.txt file
Deserializing Employee...First Name of Employee: VivekanandLast Name of Employee: Gautam
现在让我们尝试从Employee.java文件中删除“serialVersionUID”变量,然后再次运行“SerializationClass.java”文件。 它将再次创建带有对象状态的“employee.txt”文件。 现在让我们在Employee类中假设字符串地址中添加一个新变量。
Employee.java
package com.jbt;import java.io.Serializable;public class Employee implements Serializable{public String firstName;public String lastName;public String Address;//Variable is commented// private static final long serialVersionUID = 5462223600l;}
现在运行“DeserializationClass.java”并查看输出。
java.io.InvalidClassException: com.jbt.Employee; local class incompatible: stream classdesc serialVersionUID = 5462223600, local class serialVersionUID = -3607530122250644586at java.io.ObjectStreamClass.initNonProxy(Unknown Source)at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)at java.io.ObjectInputStream.readClassDesc(Unknown Source)at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)at java.io.ObjectInputStream.readObject0(Unknown Source)at java.io.ObjectInputStream.readObject(Unknown Source)at com.jbt.DeserializationClass.main(DeserializationClass.java:11)
它将引发不兼容的异常。 因为给定的类Employee.java在序列化和反序列化过程之间进行了更改。 因此,系统无法识别它仍然是同一类。 为了使我们的系统了解到它是同一类,您必须在一个类中使用serialVersionUID变量。
您可以尝试执行上述步骤,但保持serialVersionUID不变,并查看输出。 反序列化过程将正常进行。
项目要点
- 在可序列化类中定义
serialVersionUID字段不是必需的。 - 如果可序列化的类具有显式的
serialVersionUID,则此字段的类型应为long,并且必须是静态且最终的。 - 如果没有明确定义的
serialVersionUID字段,则序列化运行时将计算该类的默认值。 该值可以根据编译器的实现而变化。 因此,建议定义serialVersionUID。 - 建议对
serialVersionUID使用私有访问修饰符。 - 不同的类可以具有相同的
serialVersionUID。 - 数组类无法声明显式的
serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,无需匹配serialVersionUID值。 - 如果已加载的接收器类的
serialVersionUID与相应的发送器类之间存在差异,则将引发InvalidClassException。 - 如果要禁止序列化同一类旧版本的新类,则应对同一类的不同版本使用不同的
serialVersionUID。
@SuppressWarnings(“serial”)
如果您没有在应该序列化的类中提供serialVersionId,则编译器将给出有关该序列的警告消息。 如果要覆盖此警告,则可以使用给定的注解。 使用后,编译器将不再报错缺少的serialVersionUID。
