serialVersionUID在我看来有一个非常宽松的规范。开发具有可序列化接口的类的任何主体都可以使用InvalidClassException来烧伤他的手。另外,我看到一个使用int作为数据类型而不是长的开发者。
所以,我的问题为什么Java设计人员和开发人员没有做更具体的事情,就像我们实现可序列化时一样,我们必须实现一个设置serialVersionUID的方法,就像hashcode方法一样。
那么,我错过了什么?对我来说似乎不是一把双刃剑。
更新1:
我的坏我给出了一个错误的例子,比较一个类级别的东西和一个实例级别的东西。由于这个原因,我在不同的公司看到了许多生产问题。但我的一般想法是不能让编译器以任何方式更加严格。
答案 0 :(得分:5)
请记住要求:
现在退后一步:
结论:使用静态字段可解决以上所有问题 。当您使用方法时 - 您仍然需要创建该字段。让它沉入:当使用方法时,实现必须调用方法,将其作为字段写入字节流 - 并且在读取字节流时,需要消耗该数字 - 因为它无法映射到“真正的“班上的领域。比较一下:有一个静态字段被写入字节流并从那里读取。
所以 - 从技术的角度来看,在ID中以某种方式集成的自然方式是在类上要求静态字段。
当然你可能已经发明了别的东西。现代java 可能使用了注释。但是,当Java被发明时,这种注释的使用并不存在(并且这种序列化从第1天开始就在Java中)。 然后:现代java首先不使用“字节流”定向序列化。
或者斯蒂芬建议的答案 - 您可以根据班级的当前内容计算该ID。但同样:这项技术是20年前发明的。那时候,计算 id可能需要花费你1,5,10秒。将其与读取静态字段的努力进行比较。
答案 1 :(得分:4)
所以,我的问题为什么Java设计人员和开发人员没有做更具体的事情,就像我们实现可序列化时一样,我们必须实现一个设置serialVersionUID的方法,就像hashcode方法一样。
如果我理解正确,你说应该有一种计算serialVersion的方法。我可以看到这个问题:
应用程序如何计算出合适的串行版本?请注意,必须根据类型信息计算...而不是字段值。
在运行时(重复)计算串行版本会很昂贵。
如果我们的懒惰程序员不使用" serialver"计算正确版本号的工具,同样懒惰的程序员可能会实现这个(假设的)方法来返回一个伪造的数字......我们回到了我们开始的地方。
有些用例不是故意更改串行版本ID。
没有。懒惰程序员问题的真正解决方案是代码审查。
或者......也许......工具要么重新生成serialVersion常量,要么将它们标记为可疑。
请注意,工具无法选择所有可能出现问题的情况。但是,代码审查员也不能。代码审查员会感到疲倦,需要付费等等。
(最后,如果某些IDE没有将常量设置为-1
作为快速修复,可能是个好主意...)
但我的一般想法是不能让编译器以任何方式更加严格。
这不是编译器的事情。它是特定库类集的运行时行为。这些类使用Unsafe
...但编译器不知道serialVersionID
变量的重要性。
答案 2 :(得分:1)
为什么Java设计人员和开发人员没有[让我们]必须这样做 实现一个设置serialVersionUID
的方法
serialVersionUID是与该类相关的数据。它不是与该类的单个实例相关的数据。
如果我们有一个界面,如:
interface MySerializable
{
long getSerialVersionUID();
}
然后我们可以像这样实现:
class Foo implements MySerializable
{
private String myField;
//...
public long getSerialVersionUID()
{
if(myField.equals("hello"))
{
return 1L;
}
else
{
return 2L
}
}
}
这没有意义。版本不能依赖于实例。
既然我们有注释,我眼中的一个好解决方案是编写@Serializable
注释。我更喜欢这个,因为与序列化相关的任何事情都只是元数据。添加一个与该类行为完全无关的额外字段只会让水变得混乱。
@Serializable(ID = "1")
class Foo
{
//...
}
当然,注释是最近添加的,因此在serialVersionUID
被设计时,这不是一个选项。