# `serialVersionUID`的用途是什么

> 原文： [https://javabeginnerstutorial.com/core-java-tutorial/use-serialversionuid/](https://javabeginnerstutorial.com/core-java-tutorial/use-serialversionuid/)

在这里，我将讨论在可序列化类中使用的变量`serialVersionUID`的重要性。

下面是一个使您了解变量的确切用法的示例。

## 示例代码

`Employee.java`

```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`（此类将用于序列化）

```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`（此类将用于反序列化）

```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`对象状态的文件，然后在反序列化时从同一文件创建一个对象。 输出将如下所示。

```java
Serialized data is saved in ./employee.txt file 
```

```java
Deserializing Employee...
First Name of Employee: Vivekanand
Last Name of Employee: Gautam 
```

现在让我们尝试从`Employee.java`文件中删除“`serialVersionUID`”变量，然后再次运行“`SerializationClass.java`”文件。 它将再次创建带有对象状态的“`employee.txt`”文件。 现在让我们在`Employee`类中假设字符串地址中添加一个新变量。

`Employee.java`

```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
java.io.InvalidClassException: com.jbt.Employee; local class incompatible: stream classdesc serialVersionUID = 5462223600, local class serialVersionUID = -3607530122250644586
	at 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`。

