Java序列化中的SerialVersionUID

时间:2020-02-23 14:35:34  来源:igfitidea点击:

SerialVersionUID用于确保在Deserialization期间加载相同的类(在序列化期间使用).SerialVersionUID用于对象的版本控制。
如果我们已经使用序列化,那么我们可能已经看到SerialVersionUID,因为每当我们实现序列化接口时,IDE会给我们发出警告。

SerialVersionUID语法:

根据Java文档

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

SerialVersionUID必须是静态和最终的。
我们可以将任何号码分配给它。
让我们看一个例子:在src-> org.igi.javapostsforlearning中创建employee.java.java

1.Employee.java.

package org.igi.javapostsforlearning;
import java.io.Serializable;
public class Employee implements Serializable{
 
         private static final long serialVersionUID = 1L;
 
    int employeeId;
    String employeeName;
    String department;
    
    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}

在src-> org.igi.javapostsforlearning中创建serializemain.java

2.SerializeMain.java.

package org.igi.javapostsforlearning;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
 public class SerializeMain {
 
 /**
  * @author igi Mandliya
  */
 public static void main(String[] args) {
 
  Employee emp = new Employee();
  emp.setEmployeeId(101);
  emp.setEmployeeName("igi");
  emp.setDepartment("CS");
  try
  {
   FileOutputStream fileOut = new FileOutputStream("employee.ser");
   ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
   outStream.writeObject(emp);
   outStream.close();
   fileOut.close();
  }catch(IOException i)
  {
   i.printStackTrace();
  }
 }
}

在src-> org.igi.javapostsforlearning中创建deserializemain.java

3.deserializemain.java.

package org.igi.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;
 
public class DeserializeMain {
 /**
  * @author igi Mandliya
  */
 public static void main(String[] args) {
  
  Employee emp = null;
       try
       {
          FileInputStream fileIn =new FileInputStream("employee.ser");
          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("Deserialized Employee...");
       System.out.println("Emp id: " + emp.getEmployeeId());
       System.out.println("Name: " + emp.getEmployeeName());
       System.out.println("Department: " + emp.getDepartment());
 }
}

4.运行:

首先运行serializemain.java然后deserializemain.java,我们将得到以下输出:

Deserialized Employee...
Emp id: 101
Name: igi
Department: CS

因此,当我们运行程序时,它已成功完成,员工已在磁盘上创建。
如果我们再次运行DeserializeMain.java,则会再次成功运行。
现在将变量序列的值更改为

private static final long serialVersionUID = 2L;

如果我们现在运行deserializemain.java,它会给我们遵循错误。

java.io.InvalidClassException: org.igi.javapostsforlearning.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

所以这里在反序列化期间,我们得到了错误。
抱怨串行vvesionuid正在改变。
但它如何知道?
因为erialVersionUID是一个静态变量,我们知道"我们不能序列化静态变量"。
它是它存储序列号吗?
是的,存在异常。
erialVersionUID存在静态,它会在每次输出流时写入序列化。
ObjectInputStream读取它,如果它没有与当前版本的类中的值相同,那么它会投掷InvalidClassexception。

为什么需要serialversionuid?

实时,我们可能在文件中序列化了一个对象,并且在不同的JVM上几个月后序列化了它。
在序列化和解放类声明之间进行了更改。
所以维护版本系统和SerialVersionID是一个好主意完全相同的事情。
检查是否要为我们序列化的相同对象进行反序列化。