我知道为什么我们需要提供一个串行UID(因此在反序列化期间,发送方和接收方具有相同的加载类)。所以根据这个,如果我有多个具有类似UID的类,那么我认为反序列化会发生但是事情(我不知道是什么)之后会出错吗?或者是它会以某种方式抛出 InvalidClassException ?或者我完全偏离了我的两个假设?
我想对此进行测试但又不确定它是否会起作用会导致如果在反序列化期间实际选择了正确的类?在那种情况下,一切都将是桃子的。
答案 0 :(得分:5)
不,一点也不。通过反序列化重新创建实例时,其类由反序列化器加载。然后将此类串行UID与反序列化实例的UID进行比较,该UID是序列化时类的UID。只有当这两个UID不匹配时,才会抛出InvalidClassException
。
例如,如果将实例序列化为文件,停止JVM,使用更改的UID为此实例的类重新编译程序,重新启动应用程序并从前一个文件反序列化该实例,则会发生这种情况。 UID旨在向应用程序发出信号,表明已对该类应用了不兼容的更改。
如果具有不同完全限定名称的两个类具有相同的UID,则这不会影响您的(反)序列化。以下是the Java documentation描述此事的方式供您参考:
序列化运行时将每个可序列化类与版本号相关联,称为
serialVersionUID
,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与该方对象兼容的类序列化。如果接收者加载的对象的类别与对应的发件人类别的
serialVersionUID
不同,则反序列化将产生InvalidClassException
。可序列化类可以通过声明名为
serialVersionUID
且必须为serialVersionUID
,static
和类型final
的字段来明确声明其自己的long
。
正如您在其他评论中提到的那样,serialVersionUID
字段的类型为long
,因为它可能更小。当您没有显式设置serialVersionUID
但是如果序列化程序隐式推断出一个byte
时,这可能是为了避免冲突。在这种情况下,JVM会散列一个ID,该ID可能会与较小范围(如long
)的其他散列值轻松冲突。如果您只为每次手动更改手动增加此数字,那么您当然不可能耗尽long
的范围。一般来说,当你考虑这些天的内存价格时,单个{{1}}值既不太贵。
答案 1 :(得分:1)
不,没有什么不好的事情会发生。序列化流包含序列化对象的类的名称。一旦读取了序列化对象的类的名称,Java反序列化机制就会检查序列化的UID是否与本地类的UID相同。