每当Class implements Serializable时候,我们的目的非常明确:我要持久化.
public class Person implements Serializable {
}
持久化其实可以这么理解:我们可以通过某种方式将对象从内存块转换为可以传输或可以保存的数据流。等我们想用的时候,再用某种方式将数据流转换为内存块。
在Java中,内存块和数据流的转换我们可以使用“序列化”和“反序列化”,但是当序列化和反序列化的类不一致的情况下,JVM会抛一个InvalidClassException的异常。
比如序列化时候的对象:
public class Person implements Serializable {
private String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
反序列化时候的对象:
public class Person implements Serializable {
private String sex = "";
private String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
很明显,序列化时候和反序列化时候两个类的版本明显不同了。JVM检测出了这个版本的差异,并抛出异常。那么JVM是如何判断类的版本呢?JVM是通过流标识符(Stream Unique Identifier)来进行版本的判断的。这个流标识符分为了显式声明和隐式声明两种。
显式声明格式如下:
private static final long serialVersionUID = 8383901821872620925L;
显式声明其实也就是自己进行声明。那么隐式声明就是自己不声明,在编译的时候,编译器帮我生成。这个隐式声明的规则比较复杂,它会根据包名、类名、继承关系、非私有方法、属性以及参数、返回值等等计算得出的。
JVM在反序列化时,会比较数据流中的serialVersionUID与类的serialVersionUID是否相同,如果不同的话JVM就会抛出InvalidClassException。
显示声明可以让我们“骗过”JVM,使它认为两个版本是完全相同的,这样也是实现了反序列化向上兼容。
分享到:
相关推荐
在实现Serializable接口时,需要注意的是必须提供一个固定的serialVersionUID变量,这个变量用于标识该类的版本号,以便在反序列化时可以正确地还原对象。例如,在上面的例子中,我们定义了一个User类,并实现了...
Java 中的 serialVersionUID 是一个非常重要的概念,在实现 Serializable 接口的类中,它扮演着至关重要的角色。那么,serialVersionUID到底是什么?它又是如何生成的?在本篇文章中,我们将详细地解释 ...
在Java编程语言中,`Serializable`接口是一个非常重要的概念,它是实现对象持久化的关键。本文将深入探讨`Serializable`接口的细节,以及与其相关的高级知识。 `Serializable`接口是Java中的一个标记接口,没有包含...
这样,当我们创建一个类并实现 Serializable 接口时,IntelliJ IDEA 就会提示我们生成 serialVersionUID。 在生成 serialVersionUID 时,可以选择两种方式,一种是采用默认的 1L,即 private static final long ...
在实现 Serializable 接口的类中,如果没有显示地定义 serialVersionUID,Java 序列化机制会根据编译的 Class 自动生成一个 serialVersionUID 作序列化版本比较用。 在实际应用中,serialVersionUID 的应用场景非常...
serialVersionUID是Java语言中实现Serializable接口的类必须定义的变量,用于在反序列化时验证类的版本一致性。它是实现类持久化的重要组件,使得类可以被序列化和反序列化,从而实现了类的持久化。 在实际应用中,...
当一个类实现Serializable接口后,Java运行时系统会自动调用`writeObject()`和`readObject()`方法来完成序列化和反序列化。默认情况下,这些方法会递归地序列化类的所有字段,包括私有和静态字段。但也可以自定义...
当一个类实现`Serializable`接口后,该类的对象就可以被序列化。这个接口没有定义任何方法,仅仅作为一个标记,表明该类及其所有子类都支持序列化。需要注意的是,实现序列化的类应该谨慎处理其内部状态,因为序列化...
实现了 Serializable 接口的类需要提供一个称为 serialVersionUID 的静态final变量,该变量用于标识类的版本。 serialVersionUID serialVersionUID 是一个静态final变量,用于标识类的版本。当类的结构发生变化时...
在Java中,通过实现`Serializable`接口,可以方便地进行对象的序列化操作。序列化的核心在于能够将对象的状态转换为可以存储或传输的形式,从而实现对象的持久化和远程通信等功能。 #### 二、序列化的应用场景 ...
1. **默认序列化**:简单地实现Serializable接口,无需额外代码,适合字段较少且不关心序列化细节的场景。 2. **自定义序列化**:通过实现Externalizable接口,自定义序列化和反序列化逻辑,适合需要优化性能或有...
实现Serializable接口的类会被自动处理,无需编写额外的序列化代码,但效率相对较低。 1. 在需要序列化的类上添加`implements Serializable`:这样,Java会自动生成序列化所需的元数据,如serialVersionUID。 2. ...
当实现 `java.io.Serializable` 接口的类未明确声明 `serialVersionUID` 时,Java 序列化机制将根据编译后的 Class 文件自动生成一个 `serialVersionUID`。此规则下,即使多次重新编译,只要 Class 文件内容不变...
当一个实现了`Serializable`接口的类没有显式地声明`serialVersionUID`时,JVM会根据类的信息自动生成一个。但在某些情况下,例如在IntelliJ IDEA(简称IDEA)中开发时,开发者可能会遇到实体类实现了序列化接口却...
首先,`Serializable`接口是Java中用于实现序列化的标志接口。它没有定义任何方法,但当一个类实现了这个接口,Java的ObjectOutputStream就可以将该类的对象写入到流中。例如,`MySerializable.java`和`Product.java...
实现 `Serializable` 接口后,可以通过 `java.io.ObjectOutputStream` 将对象写入文件或通过网络传输,也可以使用 `java.io.ObjectInputStream` 从文件读取对象或将对象从网络接收。 #### 三、序列化过程 序列化的...
要使一个类可以被串行化,需要实现 Serializable 接口并提供一个 serialVersionUID 变量。 在实验中,我们定义了一个 Person 类,它实现了 Serializable 接口,并包含了 name、sex 和 age 三个属性。我们使用 ...
1. **实现Serializable接口**:实现该接口的类默认支持序列化。 2. **实现Externalizable接口**:这个接口继承自`Serializable`,提供了更高级别的控制,允许开发者自己编写序列化逻辑。 3. **序列化兼容性**:`...
在上面的例子中,我们首先定义了一个实现了 Serializable 接口的类 Serializable01,该类中有一个私有的静态、长整型常量 serialVersionUID,並且有一个私有的 byte 字段 b。然后,在 main 方法中,我们首先将对象写...
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID; 显式地定义serialVersionUID有两种用途:在某些场合,希望类的不同版本对序列化兼容,因此...