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

当缺少serialVersionUID时,Eclipse会发出警告。

可序列化的类Foo没有声明类型为long的静态最终serialVersionUID字段

什么是serialVersionUID ,为什么重要? 请显示一个示例,其中缺少serialVersionUID会导致问题。


#1楼

不用担心,默认计算确实很好,足以满足99,9999%的情况。 而且,如果遇到问题,您可以-如前所述-在需要时引入UID(这不太可能)


#2楼

serialVersionUID有助于序列化数据的版本控制。 序列化时,其值与数据一起存储。 反序列化时,将检查相同版本以查看序列化数据如何与当前代码匹配。

如果要对数据进行版本控制,通常以serialVersionUID 0开头,并在每次对类进行结构更改时更改它,从而更改序列化的数据(添加或删除非瞬态字段)。

内置的反序列化机制( in.defaultReadObject() )将拒绝从旧版本的数据中反序列化。 但是,如果您愿意,可以定义自己的readObject()函数,该函数可以读回旧数据。 然后,此自定义代码可以检查serialVersionUID ,以了解数据所在的版本并决定如何对其进行反序列化。 如果您存储在代码的多个版本中都可以生存的序列化数据,则此版本控制技术很有用。

但是存储序列化数据这么长的时间并不是很常见。 使用序列化机制将数据临时写入例如高速缓存或通过网络将其发送到具有相同版本代码库相关部分的另一个程序,这是更为常见的做法。

在这种情况下,您对保持向后兼容性不感兴趣。 您只关心确保正在通信的代码库确实具有相同版本的相关类。 为了方便进行此类检查,您必须像以前一样维护serialVersionUID ,并且在对类进行更改时不要忘记对其进行更新。

如果您忘记更新字段,则可能会遇到具有不同结构但具有相同serialVersionUID的类的两个不同版本。 如果发生这种情况,默认机制( in.defaultReadObject() )将不会检测到任何差异,并尝试对不兼容的数据进行反序列化。 现在,您可能会遇到神秘的运行时错误或静默故障(空字段)。 这些类型的错误可能很难找到。

因此,为了帮助解决该用例,Java平台为您提供了不手动设置serialVersionUID的选择。 相反,将在编译时生成类结构的哈希并将其用作id。 这种机制将确保您永远不会拥有具有相同ID的不同类结构,因此不会遇到上述难以跟踪的运行时序列化失败的情况。

但是自动生成的id策略有一个缺点。 也就是说,同一类的生成ID可能在编译器之间有所不同(如上文Jon Skeet所述)。 因此,如果在使用不同编译器编译的代码之间传递序列化数据,则建议仍然手动维护ID。

并且,如果您像提到的第一个用例那样向后兼容数据,则您可能还想自己维护ID。 为了获得可识别的ID,并更好地控制它们的更改时间和方式。


#3楼

字段数据代表存储在类中的一些信息。 类实现了Serializable接口,因此会自动提供eclipse来声明serialVersionUID字段。 让我们从此处设置的值1开始。

如果您不希望出现该警告,请使用以下命令:

@SuppressWarnings("serial")

#4楼

最初的问题要求使用“ Serial Version ID为什么有用”的“为什么重要”和“示例”。 好吧,我找到了一个。

假设您创建一个Car类,实例化它,并将其写到对象流中。 展平的汽车对象在文件系统中放置了一段时间。 同时,如果通过添加新字段来修改Car类。 稍后,当您尝试读取(即反序列化)展平的Car对象时,将获得java.io.InvalidClassException因为所有可序列化的类都会自动获得唯一的标识符。 当类的标识符与展平对象的标识符不相等时,抛出此异常。 如果您真的考虑过,则会由于添加了新字段而引发异常。 您可以通过声明显式的serialVersionUID来控制版本,从而避免抛出此异常。 显式声明您的serialVersionUID也有一个小的性能好处(因为不必计算)。 因此,最佳实践是在创建它们后立即将自己的serialVersionUID添加到Serializable类,如下所示:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}

#5楼

作为示例,其中缺少的serialVersionUID可能会导致问题:

我正在研究由使用EJB模块的Web模块组成的Java EE应用程序。 Web模块远程调用EJB模块,并传递一个实现Serializable作为参数的POJO

这个POJO's类包装在EJB jar中,并且包装在Web模块的WEB-INF / lib中自己的jar中。 它们实际上是同一类,但是当我打包EJB模块时,我解包了这个POJO的jar,将其与EJB模块打包在一起。

EJB的调用因以下异常而失败,因为我尚未声明其serialVersionUID

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52

#6楼

要了解字段serialVersionUID的重要性,应该了解序列化/反序列化的工作方式。

序列化可序列化的类对象时,Java运行时会将序列号(称为serialVersionUID)与此序列化的对象关联。 在反序列化此序列化对象时,Java Runtime会将序列化对象的serialVersionUID与该类的serialVersionUID进行匹配。 如果两者相等,则仅继续进行反序列化,否则将引发InvalidClassException。

因此,我们得出的结论是,要使序列化/反序列化过程成功进行,序列化对象的serialVersionUID必须与该类的serialVersionUID等效。 如果程序员在程序中显式指定了serialVersionUID值,则相同的值将与序列化的对象和类相关联,而与序列化和反序列化平台无关(例如,可以使用sun或MS JVM和反序列化可能使用Zing JVM在不同的平台Linux上)。

但是,如果程序员未指定serialVersionUID,则在对任何对象进行Serialization \\ DeSerialization时,Java运行时将使用其自己的算法来计算它。 这个serialVersionUID计算算法从一个JRE到另一个JRE有所不同。 序列化对象的环境也可能使用一个JRE(例如:SUN JVM),反序列化发生的环境也可能使用Linux Jvm(zing)。 在这种情况下,与序列化对象关联的serialVersionUID将与在反序列化环境下计算的类的serialVersionUID不同。 反过来,反序列化将不会成功。 因此,为避免此类情况/问题,程序员必须始终指定Serializable类的serialVersionUID。


#7楼

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

SerialVersionUID是每个类的唯一标识符, JVM使用它来比较该类的版本,以确保在反序列化期间加载序列化期间使用的同一类。

指定一个可以提供更多控制权,但是如果您未指定的话,JVM会生成一个控制权。 生成的值在不同的编译器之间可能有所不同。 此外,有时您出于某种原因只想禁止对旧的序列化对象进行反序列化[ backward incompatibility ],在这种情况下,您只需要更改serialVersionUID。

用于Serializablejavadocs

默认的serialVersionUID计算对类详细信息高度敏感,类详细信息可能会根据编译器的实现而有所不同,因此可能在反序列化期间导致意外的InvalidClassException

因此,您必须声明serialVersionUID,因为它可以提供更多控制权

本文对此主题有一些好处。


#8楼

我通常在一种上下文中使用serialVersionUID :当我知道它将离开Java VM的上下文时。

当我为应用程序使用ObjectInputStreamObjectOutputStream ,或者如果我知道我使用的库/框架将使用它时,我就会知道这一点。 所述serialVersionID确保不同版本或供应商的不同的Java虚拟机将互操作正确,或者如果它被存储和检索的VM外部例如HttpSession会话数据可以在重启期间保持甚至和升级应用程序服务器的。

对于所有其他情况,我使用

@SuppressWarnings("serial")

因为大多数情况下,默认的serialVersionUID就足够了。 这包括ExceptionHttpServlet


#9楼

您将得到有关java.io.Serializable的文档最佳解释:

序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID ,该序列号在反序列化期间用于验证序列化对象的发送者和接收者是否已加载了该对象的与序列化兼容的类。 如果接收者已为该对象加载了一个与相应发送者类具有不同的serialVersionUID的类,则反序列化将导致InvalidClassException 。 可序列化的类可以通过声明一个名为serialVersionUID的字段来显式声明其自己的serialVersionUID ,该字段必须是静态的,最终的且类型为long

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

如果可序列化的类未显式声明serialVersionUID ,则序列化运行时将根据该类的各个方面,为该类计算默认的serialVersionUID值,如Java(TM)对象序列化规范中所述。 但是, 强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类详细信息高度敏感,而类详细信息可能会根据编译器的实现而有所不同,因此可能在反序列化期间导致意外的InvalidClassExceptions 。 因此,为了保证不同Java编译器实现之间的serialVersionUID值一致,可序列化的类必须声明一个显式的serialVersionUID值。 强烈建议显式serialVersionUID声明在可能的情况下使用private修饰符,因为此类声明仅适用于立即声明的类serialVersionUID字段作为继承成员不起作用。


#10楼

如果您永远不需要将对象序列化为字节数组并发送/存储它们,则不必担心。 如果这样做,则必须考虑您的serialVersionUID,因为对象的反序列化器会将其与其类加载器所具有的对象版本进行匹配。 在Java语言规范中阅读有关它的更多信息。


#11楼

我不能错过这个机会来插上乔什·布洛赫(Josh Bloch)的书《 有效的Java》 (第二版)。 第11章是有关Java序列化的必不可少的资源。

Per Josh会根据类名称,已实现的接口以及所有公共成员和受保护成员来生成自动生成的UID。 以任何方式更改其中任何一个都将更改serialVersionUID 。 因此,仅在确定不会对一个以上版本的类进行序列化(跨进程或在以后的时间从存储中检索)时,您才无需弄乱它们。

如果您暂时忽略它们,然后以后发现需要以某种方式更改类但要保持与旧版本的兼容性,则可以使用JDK工具serialver类上生成serialVersionUID ,并进行显式设置在新班上。 (根据您的更改,您可能还需要通过添加writeObjectreadObject方法来实现自定义序列化-请参见Serializable javadoc或前面提到的第11章。)


#12楼

您可以告诉Eclipse忽略以下serialVersionUID警告:

窗口>首选项> Java>编译器>错误/警告>潜在的编程问题

如果您不知道,您可以在本节中启用很多其他警告(甚至有一些警告报告为错误),其中许多警告非常有用:

  • 潜在的编程问题:可能的意外布尔分配
  • 潜在的编程问题:空指针访问
  • 不必要的代码:永远不会读取局部变量
  • 不必要的代码:冗余null检查
  • 不必要的代码:不必要的强制转换或'instanceof'

还有很多。


#13楼

如果您只是为了实现的需要而进行序列化(例如,谁在乎是否为HTTPSession进行序列化,...是否存储了de-serializing ,则可能不关心对de-serializing对象进行de-serializing )而de-serializing ,那么您可以忽略此。

如果您实际上正在使用序列化,则仅在计划直接使用序列化存储和检索对象时才重要。 serialVersionUID表示您的类版本,如果您的类的当前版本与它的先前版本不向后兼容,则应该递增它。

大多数时候,您可能不会直接使用序列化。 如果是这种情况, SerialVersionUID通过单击快速修复选项来生成默认的SerialVersionUID ,不用担心。


#14楼

SerialVersionUID用于对象的版本控制。 您也可以在类文件中指定serialVersionUID。 不指定serialVersionUID的后果是,当您添加或修改类中的任何字段时,已序列化的类将无法恢复,因为为新类和为旧的序列化对象生成的serialVersionUID将有所不同。 Java序列化过程依赖于正确的serialVersionUID来恢复序列化对象的状态,并在serialVersionUID不匹配的情况下抛出java.io.InvalidClassException

了解更多: http : //javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ


#15楼

如果要修改大量没有设置serialVersionUID的类,同时又要与旧类保持兼容,则IntelliJ Idea,Eclipse之类的工具会因为生成随机数而无法使用,无法在大量文件上使用一气呵成。 我提出以下bash脚本(对于Windows用户感到抱歉,请考虑购买Mac或转换为Linux),以轻松解决serialVersionUID问题:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               

while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

您保存此脚本,对您〜/ bin说add_serialVersionUID.sh。 然后在Maven或Gradle项目的根目录中运行它,如下所示:

add_serialVersionUID.sh < myJavaToAmend.lst

该.lst包含用于以以下格式添加serialVersionUID的Java文件列表:

com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

该脚本在后台使用JDK serialVer工具。 因此,请确保$ JAVA_HOME / bin在PATH中。


#16楼

约书亚·布洛赫(Joshua Bloch)在《有效的Java》中很好地记录了这个问题。 一本非常好的书,必读。 我将在下面概述一些原因:

序列化运行时为每个可序列化的类提供了一个称为序列号的编号。 此数字称为serialVersionUID。 现在,这个数字后面有一些数学运算,它是根据类中定义的字段/方法得出的。 对于相同的类,每次都会生成相同的版本。 在反序列化过程中使用此数字来验证序列化对象的发送者和接收者是否已为该对象加载了与序列化兼容的类。 如果接收者已为该对象加载了一个与相应发送者类具有不同的serialVersionUID的类,则反序列化将导致InvalidClassException。

如果该类是可序列化的,则还可以通过声明一个名称为“ serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的,最终的且类型为long。 像Eclipse这样的大多数IDE都可以帮助您生成该长字符串。


#17楼

如果CheckStyle可以验证实现Serializable的类上的serialVersionUID具有良好的值,即它与串行版本ID生成器所生成的值匹配,那将是很好的选择。 例如,如果您的项目具有大量可序列化的DTO,记得记住删除现有的serialVersionUID并重新生成它是一件很麻烦的事,而目前(我所知道的)验证此方法的唯一方法是为每个类重新生成并进行比较旧的。 这是非常非常痛苦的。


#18楼

每次对对象进行序列化时,都会在该对象上标记该对象的类的版本ID号。此ID称为serialVersionUID ,它是基于有关类结构的信息计算的。 假设您创建了一个Employee类,并且它的版本ID为#333(由JVM分配),现在,当您序列化该类的对象(假设Employee对象)时,JVM将为其分配UID为#333。

考虑一种情况-将来您需要编辑或更改您的类,并且在这种情况下,当您对其进行修改时,JVM会为其分配一个新的UID(假设#444)。 现在,当您尝试反序列化员工对象时,JVM会将序列化对象(员工对象)的版本ID(#333)与该类的ID(即#444)进行比较(因为它已更改)。 相比之下,JVM将发现两个版本的UID不同,因此反序列化将失败。 因此,如果每个类的serialVersionID由程序员自己定义。 即使该类将来进行了开发,它也将是相同的,因此即使更改了该类,JVM也会始终发现该类与序列化对象兼容。 有关更多信息,请参见HEAD FIRST JAVA的第14章。


#19楼

为什么要在Java的Serializable类中使用SerialVersionUID

serialization ,Java运行时为类创建版本号,以便稍后可以反序列化。 此版本号在Java中称为SerialVersionUID

SerialVersionUID用于对序列化数据进行版本控制。 如果类的SerialVersionUID与序列化的实例匹配,则只能反序列化该类。 当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但不建议这样做。 建议将SerialVersionUID声明为private static final long变量,以避免使用默认机制。

通过实现标记接口java.io.Serializable一个类声明为Serializable时,如果您尚未使用Externalizable接口自定义该过程,则Java运行时将使用默认的Serialization机制将该类的实例持久化到磁盘中。

另请参见为什么在Java的Serializable类内使用SerialVersionUID

程式码: javassist.SerialVersionUID


#20楼

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

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

有一些序列化规则

  • 仅当对象的类或其超类实现Serializable接口时,该对象才可序列化

  • 一个对象是可序列化的(本身实现了Serializable接口),即使其超类不是。 但是,可序列化类的层次结构中的第一个超类(不实现Serializable接口)必须具有无参数构造函数。 如果违反此规定,则readObject()将在运行时生成java.io.InvalidClassException

  • 所有原始类型都是可序列化的。

  • 暂态字段(带有暂态修饰符)未序列化(即,未保存或恢复)。 实现Serializable的类必须标记不支持序列化的类(例如文件流)的瞬态字段。

  • 静态字段(带有static修饰符)未序列化。

序列化Object时,Java Runtime会将序列号也称为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)

#21楼

如果在类上收到此警告,则永远不要考虑进行序列化,并且也没有声明自己implements Serializable ,这通常是因为您从实现了Serializable的超类继承而来。 通常,最好委托给这样的对象,而不要使用继承。

所以,代替

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

并在相关方法中调用myList.foo()而不是this.foo() (或super.foo() )。 (这并不适合所有情况,但仍然很常见。)

我经常看到人们扩展JFrame之类的东西,而实际上他们只需要委托给它即可。 (这也有助于在IDE中自动完成,因为JFrame具有数百种方法,当您要在类上调用自定义方法时就不需要这些方法。)

警告(或serialVersionUID)不可避免的一种情况是,当您从AbstractAction扩展时,通常是在一个匿名类中,仅添加actionPerformed方法。 我认为在这种情况下不应该发出警告(因为您通常无法跨类的不同版本可靠地序列化和反序列化此类匿名类),但是我不确定编译器如何识别这一点。


#22楼

简单说明:

  1. 您要序列化数据吗?

    序列化基本上是将类数据写入文件/流/等。 反序列化将数据读回到类中。

  2. 您打算投产吗?

    如果您仅测试不重要/伪造的数据,则不必担心(除非您直接测试序列化)。

  3. 这是第一个版本吗?

    如果是这样,请设置serialVersionUID=1L

  4. 这是第二,第三等产品版本吗?

    现在,您需要担心serialVersionUID ,并应该对其进行深入研究。

基本上,如果在更新需要写入/读取的类时未正确更新版本,则在尝试读取旧数据时会出现错误。


#23楼

简而言之,此字段用于检查序列化数据是否可以正确反序列化。 序列化和反序列化通常由程序的不同副本进行-例如,服务器将对象转换为字符串,而客户端将收到的字符串转换为对象。 该字段告诉双方,对于该对象是什么,它们具有相同的想法。 该字段在以下情况下有帮助:

  • 您在不同的地方(例如1个服务器和100个客户端)有许多不同的程序副本。 如果您要更改对象,更改版本号而忘记更新此客户端,则它将知道他无法反序列化

  • 您已将数据存储在某个文件中,然后稍后尝试使用带有修改对象的程序的更新版本打开它-如果您保持正确的版本,则将知道此文件不兼容

什么时候重要?

最明显的是-如果将一些字段添加到对象中,则较旧的版本将无法使用它们,因为它们的对象结构中没有这些字段。

不太明显-在反序列化对象时,字符串中不存在的字段将保留为NULL。 如果您已从对象中删除了字段,则较旧的版本会将字段保留为allways-NULL,如果较旧的版本依赖于此字段中的数据,则可能导致行为异常(无论如何,您都是出于某种目的而创建它的:-))

最不明显-有时您更改了某些领域含义中的想法。 例如,当您12岁时,“自行车”下的意思是“自行车”,但是当您18岁时,您的意思是“摩托车”-如果您的朋友邀请您“骑自行车穿越城市”,那么您将是唯一一个骑自行车,您将无法理解在各个领域保持相同含义的重要性:-)


#24楼

首先回答您的问题,当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但是该过程对许多类元数据敏感,包括字段数,字段类型,字段访问修饰符,实现的接口因此,建议自行声明它,Eclipse会警告您同样的事情。

序列化:我们经常与重要对象一起工作,这些对象的状态(对象变量中的数据)是如此重要,以至于在将对象状态发送给其他对象的情况下,我们不会因为电源/系统故障(或网络故障)而丢失它机。 此问题的解决方案称为“持久性”,它仅表示持久性(保存/保存)数据。 序列化是实现持久性的许多其他方法之一(通过将数据保存到磁盘/内存)。 保存对象的状态时,重要的是为对象创建一个标识,以便能够正确地将其读回(反序列化)。 此唯一标识是ID,是SerialVersionUID。


#25楼

什么是SerialVersionUID? 答案:-假设有两个人,一个来自总部,另一个来自ODC,都将分别执行序列化和反序列化。 在这种情况下,为了验证ODC中的接收者是经过身份验证的人,JVM会创建一个唯一ID,称为SerialVersionUID。

根据场景,这是一个很好的解释,

为什么选择SerialVersionUID?

序列化 :在序列化时,每个对象发送方JVM都会保存一个唯一标识符。 JVM负责根据发送方系统中存在的相应.class文件生成该唯一ID。

反序列化 :反序列化时,接收方JVM将与对象关联的唯一ID与本地类Unique ID进行比较,即JVM还将基于接收方系统中存在的相应.class文件创建唯一ID。 如果两个唯一ID都匹配,则将仅执行反序列化。 否则,我们将获得Runtime Exception,显示InvalidClassException。 这个唯一的标识符不过是SerialVersionUID

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值