serialVersionUID
缺少a时,Eclipse发出警告。
可序列化的类Foo没有声明类型为long的静态最终serialVersionUID字段
是什么serialVersionUID
,为什么重要?请显示一个示例,其中缺失serialVersionUID
会导致问题。
serialVersionUID
缺少a时,Eclipse发出警告。
可序列化的类Foo没有声明类型为long的静态最终serialVersionUID字段
是什么serialVersionUID
,为什么重要?请显示一个示例,其中缺失serialVersionUID
会导致问题。
Answers:
java.io.Serializable
您可能会得到的有关文档的解释很好:
序列化运行时与每个可序列化的类关联一个版本号,称为
serialVersionUID
,在反序列化期间使用该版本号来验证序列化对象的发送者和接收者是否已加载了该对象的与序列化兼容的类。如果接收者为对象加载的类serialVersionUID
与相应的发送者的类不同,则反序列化将导致InvalidClassException
。可序列化的类可以serialVersionUID
通过声明一个serialVersionUID
必须为static,final和type 的字段来显式声明其自身long
:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化的类未显式声明a
serialVersionUID
,则序列化运行时将根据serialVersionUID
该类的各个方面为该类计算默认值,如Java™对象序列化规范中所述。但是,强烈建议所有可序列化的类显式声明serialVersionUID
值,因为默认的情况下serialVersionUID
计算对类详细信息高度敏感,而类详细信息可能会根据编译器的实现而有所不同,因此可能导致InvalidClassExceptions
反序列化期间发生意外情况。因此,为了保证serialVersionUID
不同Java编译器实现之间的值一致,可序列化的类必须声明一个显式serialVersionUID
值。还强烈建议明确serialVersionUID
声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类serialVersionUID
字段,不能用作继承成员。
如果您只是为了实现的需要而进行序列化(例如,谁在乎是否为序列化HTTPSession
……如果它是否已存储,那么您可能不在乎de-serializing
表单对象),就可以进行序列化。忽略这个。
如果您实际上正在使用序列化,则仅当您计划直接使用序列化来存储和检索对象时才重要。该serialVersionUID
代表你的类版本,你应该增加,如果你的类的当前版本不向后与以前的版本兼容。
大多数时候,您可能不会直接使用序列化。在这种情况下,请SerialVersionUID
通过单击快速修复选项生成默认值,不必担心。
serialVersionUID
保护您免受不兼容更改的影响是正确的。@SuppressWarnings
如果您不希望将该类用于永久存储,则使用文档的意图会更好。
serialVersionUID
是万不得已,绝望的顾问。
我不能错过这个机会来插上乔什·布洛赫(Josh Bloch)的书《有效的Java》(第二版)。第11章是有关Java序列化的必不可少的资源。
Per Josh会根据类名称,已实现的接口以及所有公共成员和受保护成员来生成自动生成的UID。以任何方式更改其中任何一项都会更改serialVersionUID
。因此,仅在确定不会对一个以上版本的类进行序列化(跨进程或在以后的时间从存储中检索)时,您才无需弄乱它们。
如果你忽略他们,现在,以后,你需要更改类以某种方式,但保持兼容性瓦特/旧版本的类,你可以使用JDK工具发现的serialver生成serialVersionUID
对旧类,并明确设置在新班上。(根据您的更改,您可能还需要通过添加writeObject
和readObject
方法来实现自定义序列化-请参阅Serializable
javadoc或前面提到的第11章。)
您可以告诉Eclipse忽略以下serialVersionUID警告:
窗口>首选项> Java>编译器>错误/警告>潜在的编程问题
如果您不知道,您可以在本节中启用很多其他警告(甚至有一些报告为错误),许多警告非常有用:
还有很多。
serialVersionUID
便于序列化数据的版本控制。序列化时,其值与数据一起存储。反序列化时,将检查相同版本以查看序列化数据如何与当前代码匹配。
如果要版本化数据,通常以 serialVersionUID
0,然后对类进行每次结构更改,以改变序列化的数据(添加或删除非瞬态字段),然后对其进行修改。
内置的反序列化机制(in.defaultReadObject()
)将拒绝对旧版本的数据进行反序列化。但是,如果您愿意,可以定义自己的readObject()函数,该函数可以读回旧数据。然后,此自定义代码可以检查serialVersionUID
,以了解数据所在的版本并决定如何对其进行反序列化。如果您存储在代码的多个版本中都可以生存的序列化数据,则此版本控制技术很有用。
但是存储序列化数据这么长的时间并不是很常见。使用序列化机制临时将数据临时写入例如缓存,或者通过网络将其发送到具有相同版本代码库相关部分的另一个程序,这是更为常见的做法。
在这种情况下,您对保持向后兼容性不感兴趣。您只关心确保正在通信的代码库确实具有相同版本的相关类。为了方便进行此类检查,您必须维护serialVersionUID
像以前一样原样,并且在更改类时不要忘记对其进行更新。
如果您忘记更新字段,则可能会遇到具有不同结构但具有相同的类的两个不同版本serialVersionUID
。如果发生这种情况,默认机制(in.defaultReadObject()
)将不会检测到任何差异,并尝试对不兼容的数据进行反序列化。现在,您可能会遇到神秘的运行时错误或静默故障(空字段)。这些类型的错误可能很难找到。
因此,为了帮助解决该用例,Java平台为您提供了不serialVersionUID
手动设置选项。相反,将在编译时生成类结构的哈希并将其用作id。这种机制将确保您永远不会拥有具有相同ID的不同类结构,因此不会遇到上述难以跟踪的运行时序列化失败的情况。
但是自动生成的id策略有一个缺点。也就是说,同一类的生成ID可能在编译器之间有所不同(如上文Jon Skeet所述)。因此,如果在使用不同编译器编译的代码之间传递序列化数据,则建议仍然手动维护ID。
并且,如果您像提到的第一个用例那样向后兼容数据,则您可能还想自己维护ID。为了获得可识别的ID,并更好地控制它们的更改时间和方式。
什么是serialVersionUID,为什么要使用它?
SerialVersionUID
是每个类的唯一标识符,JVM
使用它来比较该类的版本,以确保在反序列化期间加载序列化期间使用的同一类。
指定一个可以提供更多控制权,但是如果您未指定的话,JVM会生成一个控制权。生成的值在不同的编译器之间可能有所不同。此外,有时您只是出于某种原因希望禁止对旧的序列化对象[ backward incompatibility
]进行反序列化,在这种情况下,您只需要更改serialVersionUID。
默认的serialVersionUID计算对类详细信息高度敏感,类详细信息可能会根据编译器的实现而有所不同,因此可能会
InvalidClassException
在反序列化期间导致意外的。
因此,您必须声明serialVersionUID,因为它可以提供更多控制权。
本文对此主题有一些好处。
serialVersionUID
不知不觉地盲目地这样做,可能会导致意想不到的后果。汤姆·安德森(Tom Anderson)对MetroidFan2002答案的评论解决了此问题:“我想说的是,如果您不使用序列化来永久存储,则应使用@SuppressWarnings而不是添加值。它会使类混乱,并且保留了类的能力。 serialVersionUID机制可保护您免受不兼容的更改的影响。”
serialVersionUID
是不是一个“用于每个类别的唯一标识符”。完全合格的类名称是那个。它是一个版本指示器。
最初的问题要求“为什么重要”和“示例”,在此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
}
1
,依此类推。
首先,我需要解释什么是序列化。
序列化允许将对象转换为流,以便通过网络发送该对象,或者保存到文件或保存到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)
如果您永远不需要将对象序列化为字节数组并发送/存储它们,则不必担心。如果这样做,则必须考虑您的serialVersionUID,因为对象的反序列化器会将其与其类加载器所具有的对象版本进行匹配。在Java语言规范中阅读有关它的更多信息。
如果在类上收到此警告,则永远不会考虑序列化,也不会声明自己 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方法。我认为在这种情况下不应该发出警告(因为您通常无法跨类的不同版本可靠地序列化和反序列化此类匿名类),但是我不确定编译器如何识别这一点。
__AUTOLOAD
,但我不知道。
要了解字段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。
不用担心,默认计算确实很好,足以满足99,9999%的情况。而且,如果遇到问题,您可以-如前所述-在需要时引入UID(这不太可能)
作为示例,其中缺少的serialVersionUID可能会导致问题:
我正在研究由使用EJB
模块的Web模块组成的Java EE应用程序。Web模块EJB
远程调用该模块并传递POJO
实现的Serializable
为参数的。
这个 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
我通常serialVersionUID
在一种上下文中使用:当我知道它将离开Java VM的上下文时。
我会在使用ObjectInputStream
和ObjectOutputStream
应用程序时知道这一点,或者如果知道使用的库/框架会使用它。serialVersionID确保不同版本或供应商的不同Java VM可以正确互操作,或者确保它在VM外部存储和检索(例如)HttpSession
,即使重新启动和升级应用程序服务器,会话数据也可以保留。
对于所有其他情况,我使用
@SuppressWarnings("serial")
因为大多数时候默认值serialVersionUID
就足够了。这包括Exception
,HttpServlet
。
如果CheckStyle可以验证实现Serializable的类上的serialVersionUID具有良好的值,即它与串行版本ID生成器所生成的值匹配,那将是很好的选择。例如,如果您的项目包含大量可序列化的DTO,记得记住删除现有的serialVersionUID并重新生成它是一件很麻烦的事,并且(目前我所知道的)唯一可以验证此方法的方法是为每个类重新生成并进行比较。旧的。这是非常非常痛苦的。
serialver
会产生的结果。-1
serialVersionUID
为1。如果该类的较新版本不兼容,但仍要求能够处理旧数据,则可以增加版本号并向其中添加特殊代码处理较旧的格式。每当看到serialVersionUID
大于1的数字时,我都会哭泣,要么是因为它是一个随机数(无用),要么是因为该类显然需要处理10个以上的不同版本。
SerialVersionUID用于对象的版本控制。您也可以在类文件中指定serialVersionUID。不指定serialVersionUID的后果是,当您添加或修改类中的任何字段时,已序列化的类将无法恢复,因为为新类和为旧的序列化对象生成的serialVersionUID将有所不同。Java序列化过程依赖于正确的serialVersionUID来恢复序列化对象的状态,并在serialVersionUID不匹配的情况下抛出java.io.InvalidClassException
了解更多:http : //javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ
为什么在Java中使用SerialVersionUID
内部Serializable
类?
在期间serialization
,Java运行时为类创建版本号,以便稍后可以反序列化。此版本号SerialVersionUID
在Java中是已知的。
SerialVersionUID
用于版本化序列化数据。如果类SerialVersionUID
与已序列化的实例匹配,则只能对它进行反序列化。当我们不在SerialVersionUID
类中声明时,Java运行时会为我们生成它,但不建议这样做。建议声明SerialVersionUID
为private static final long
变量以避免默认机制。
如果Serializable
通过实现标记接口将类声明为java.io.Serializable
,则Java运行时将使用默认的序列化机制将该类的实例持久化到磁盘中,前提是您尚未使用Externalizable
接口自定义流程。
如果要修改大量没有设置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中。
约书亚·布洛赫(Joshua Bloch)在《有效的Java》中很好地记录了这个问题。一本非常好的书,必读。我将在下面概述一些原因:
序列化运行时为每个可序列化的类提供了一个称为序列号的编号。此数字称为serialVersionUID。现在,该数字后面有一些数学运算,它基于类中定义的字段/方法得出。对于相同的类,每次都会生成相同的版本。在反序列化过程中使用此数字来验证序列化对象的发送者和接收者是否已为该对象加载了与序列化兼容的类。如果接收者已为该对象加载了一个与相应发送者类具有不同的serialVersionUID的类,则反序列化将导致InvalidClassException。
如果该类是可序列化的,则还可以通过声明一个名称为“ serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的,最终的且类型为long。像Eclipse这样的大多数IDE都可以帮助您生成该长字符串。
每次对对象进行序列化时,都会在该对象上标记该对象的类的版本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章。
serialVersionUID
都会发送一次。并非随每个对象一起发送。
“ serialVersionUID”是一个64位数字,用于在反序列化过程中唯一地标识类。序列化对象时,该类的serialVersionUID也会写入文件中。每当您反序列化此对象时,java运行时就会从序列化的数据中提取此serialVersionUID值,并将与该类关联的相同值进行比较。如果两者都不匹配,则将抛出“ java.io.InvalidClassException”。
如果可序列化的类未明确声明serialVersionUID,则序列化运行时将根据类的各个方面(例如字段,方法等)为该类计算serialVersionUID值,您可以参考此链接以进行演示应用程序。
简而言之,此字段用于检查序列化数据是否可以正确反序列化。序列化和反序列化通常由程序的不同副本进行-例如,服务器将对象转换为字符串,而客户端将收到的字符串转换为对象。该字段告诉双方,对于该对象是什么,它们具有相同的想法。该字段在以下情况下有帮助:
您在不同的地方(例如1个服务器和100个客户端)有许多不同的程序副本。如果您要更改对象,更改版本号而忘记更新此客户端,则它将知道他无法反序列化
您已将数据存储在某个文件中,然后稍后尝试使用带有修改对象的程序的更新版本打开它-如果您保持正确的版本,则将知道此文件不兼容
什么时候重要?
最明显的是-如果将一些字段添加到对象中,则较旧的版本将无法使用它们,因为它们的对象结构中没有这些字段。
不太明显-在反序列化对象时,字符串中不存在的字段将保留为NULL。如果您已从对象中删除了字段,则较旧的版本会将字段保留为allways-NULL,如果较旧的版本依赖于此字段中的数据,则可能导致行为异常(无论如何,您都是出于某种目的而创建它的:-))
最不明显-有时您更改了某些领域含义中的想法。例如,当您12岁时,“自行车”下的意思是“自行车”,但是当您18岁时,您的意思是“摩托车”-如果您的朋友邀请您“骑自行车穿越城市”,那么您将是唯一一个骑自行车,您将无法理解在各个领域保持相同含义的重要性:-)
首先回答您的问题,当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但是该过程对许多类元数据敏感,包括字段数,字段类型,字段访问修饰符,实现的接口因此,建议自行声明它,Eclipse会警告您同样的事情。
序列化:我们经常与重要对象一起工作,这些对象的状态(对象变量中的数据)是如此重要,以至于在将对象状态发送给其他对象的情况下,我们不会因为电源/系统故障(或网络故障)而丢失它机。此问题的解决方案称为“持久性”,它仅表示持久性(保存/保存)数据。序列化是实现持久性的许多其他方法之一(通过将数据保存到磁盘/内存)。保存对象的状态时,重要的是为对象创建一个标识,以便能够正确地读回它(反序列化)。此唯一标识是ID,是SerialVersionUID。
什么是SerialVersionUID?答案:-假设有两个人,一个来自总部,另一个来自ODC,都将分别执行序列化和反序列化。在这种情况下,为了验证ODC中的接收者是经过身份验证的人,JVM会创建一个唯一ID,称为SerialVersionUID。
根据场景,这是一个很好的解释,
为什么选择SerialVersionUID?
序列化:在序列化时,每个对象发送方JVM都会保存一个唯一标识符。JVM负责根据发送方系统中存在的相应.class文件生成该唯一ID。
反序列化:反序列化时,接收方JVM将与对象关联的唯一ID与本地类Unique ID进行比较,即JVM还将基于接收方系统中存在的相应.class文件创建唯一ID。如果两个唯一的ID都匹配,则将仅执行反序列化。否则,我们将获得Runtime Exception,说明InvalidClassException。这个唯一的标识符不过是SerialVersionUID