当前位置: 首页 > 面试题库 >

什么是serialVersionUID,为什么要使用它?

吴欣悦
2023-03-14
问题内容

serialVersionUID缺少a时,Eclipse发出警告。

The serializable class Foo does not declare a static final serialVersionUID field of type long

问题答案:

首先,我需要解释什么是序列化。

序列化 允许将对象转换为流,以便通过网络发送该对象,或者保存到文件或保存到DB以供使用。

有一些序列化规则。

  • 仅当对象的类或其超类实现Serializable接口时,该对象才可序列化
  • 一个对象是可序列化的(本身实现了Serializable接口),即使其超类不是。但是,可序列化类的层次结构中的第一个超类(不实现Serializable接口)必须具有无参数构造函数。如果违反此规定,则readObject()将在运行时生成java.io.InvalidClassException
  • 所有原始类型都是可序列化的。
  • 暂态字段(带有暂态修饰符)未序列化(即,未保存或恢复)。实现Serializable的类必须标记不支持序列化的类(例如文件流)的瞬态字段。
  • 静态字段(带有static修饰符)未序列化。

当Object被序列化,Java运行时关联的序列版本号又名的serialVersionID。

我们需要serialVersionID的位置: 在反序列化期间,验证发送者和接收者在序列化方面是否兼容。如果接收者给类加载了另一个类,serialVersionID反序列化将以结束InvalidClassCastException。
可序列化的类可以serialVersionUID通过声明一个serialVersionUID必须为静态,最终且类型为long的字段来显式声明其自身。

让我们尝试一个例子。

import java.io.Serializable;    
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;

public String getEmpName() {
    return name;
}
public void setEmpName(String empname) {
    this.empname = empname;
}
public byte getEmpAge() {
    return empage;
}
public void setEmpAge(byte empage) {
    this.empage = empage;
}

public String whoIsThis() {
    StringBuffer employee = new StringBuffer();
    employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old  "));
    return employee.toString();
}
}

创建序列化对象

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
    Employee employee = new Employee();
    employee.setEmpName("Jagdish");
    employee.setEmpAge((byte) 30);

    FileOutputStream fout = new
FileOutputStream("/users/Jagdish.vala/employee.obj");
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(employee);
    oos.close();
    System.out.println("Process complete");
}
}

反序列化对象

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException,
IOException {
    Employee employee = new Employee();
    FileInputStream fin = new
    FileInputStream("/users/Jagdish.vala/employee.obj");
    ObjectInputStream ois = new ObjectInputStream(fin);
    employee = (Employee) ois.readObject();
    ois.close();
    System.out.println(employee.whoIsThis());
 }
}    

注意:现在更改Employee类的serialVersionUID并保存:

private static final long serialVersionUID = 4L;

并执行Reader类。不执行Writer类,你将获得异常。

Exception in thread "main" java.io.InvalidClassException:
com.jagdish.vala.java.serialVersion.Employee; local class incompatible:
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)


 类似资料:
  • Bootstrapping(引导) 是 Netty 中配置程序的过程,当你需要连接客户端或服务器绑定指定端口时需要使用 Bootstrapping。 如前面所述,Bootstrapping 有两种类型,一种是用于客户端的Bootstrap,一种是用于服务端的ServerBootstrap。不管程序使用哪种协议,无论是创建一个客户端还是服务器都需要使用“引导”。 面向连接 vs. 无连接 请记住,这

  • 问题内容: 什么是Unix时间戳?在PHP中,使用日期时,该函数输出一些整数值- 那是什么?我尝试了解这一点,但无法获得满意的答案,尤其是为什么我们需要使用转换日期。 问题答案: 什么是Unix时间戳 简而言之,Unix时间戳是一种跟踪时间(以秒为单位)的方式。此计数从1970年1月1日UTC的Unix Epoch开始。因此, Unix时间戳仅仅是特定日期和Unix Epoch之间的秒数 。还应该

  • 问题内容: 我尝试阅读一些文章,但对这个主题不太清楚。 有人想向我解释以下几点: 为什么通过HTTP使用websocket 什么是全双工通信 延迟延迟交互是什么意思 问题答案: 为什么通过HTTP使用websocket? webSocket是客户端和服务器之间的连续连接。该连续连接允许以下操作: 数据可以随时从服务器发送到客户端,而客户端甚至不需要请求。这通常称为服务器推送,对于客户端需要在服务器

  • 问题内容: 我正在尝试使用此命令安装Python软件包 我收到权限错误,不确定为什么。我可以使用来运行它,但是有人告诉我这是个坏主意,我应该改用virtualenv。 什么是虚拟环境?它对我有什么作用? 问题答案: 与系统Python和库一起运行会将您限制为OS提供商选择的一个特定Python版本。试图在一个Python安装上运行所有Python应用程序,可能会导致库集合之间发生版本冲突。对系统P

  • 本文向大家介绍什么是闭包(closure)为什么要用它相关面试题,主要包含被问及什么是闭包(closure)为什么要用它时的应答技巧和注意事项,需要的朋友参考一下 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。 闭包的特性: 1.函数内再嵌套函数

  • 问题内容: 我经常在PHP中看到包含include.inc文件的示例。.inc是什么意思?它的作用是什么?使用它的缺点和优点是什么? 问题答案: 它没有任何意义,只是一个文件扩展名。如果扩展名是.inc的文件被设计为包含在其他PHP文件中,这是某些人的惯例,但这只是惯例。 它确实存在一个可能的缺点,即通常没有将服务器配置为将.inc文件解析为php,因此,如果该文件位于您的Web根目录中,并且您的