我正在尝试学习序列化如何与Java及其最新版本一起使用。我正在尝试像这样序列化一个lambda:
Runnable r = (Runnable & Serializable)() -> {System.out.println("This is a test");};
但我注意到我没有关于缺少serialVersionUID
变量的警告。这是正常的吗?
我知道它会在运行时生成,但强烈建议您定义它:https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html
如果可序列化类没有显式声明serialVersionUID,那么序列化运行时将计算a 基于各个方面的该类的默认serialVersionUID值 该类的类,如Java(TM)对象序列化中所述 规格。但是,强烈建议所有人 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类非常敏感 细节可能因编译器实现而异,并且可以 因此导致意外的InvalidClassExceptions期间 反序列化。因此,要保证一致的serialVersionUID 不同java编译器实现的值,可序列化 class必须声明一个显式的serialVersionUID值。也是 强烈建议显式serialVersionUID声明使用 尽可能使用私有修饰符,因为此类声明仅适用于 立即声明的类 - serialVersionUID字段不是 作为继承成员有用。数组类不能声明显式 serialVersionUID,所以它们总是有默认的计算值,但是 免除匹配serialVersionUID值的要求 数组类。
我该怎么办?如何在我的Lambda中定义它?
由于
答案 0 :(得分:6)
serialVersionUID
仅与生成stream identifier的类相关。如果可序列化类具有返回不同类的替换对象的writeReplace()
方法(也在Serializable
documentation中描述),则不是这种情况,因为这样的表示与原始类完全分离。这是可序列化的lambda实例所发生的情况,请参阅SerializedLambda
:
可序列化lambda的实现者,例如编译器或语言运行库,应该确保实例正确地反序列化。一种方法是确保
writeReplace
方法返回SerializedLambda
的实例,而不是允许默认序列化继续进行。
因此,它是SerializedLambda
的一个实例,最终在流上,因此该类具有稳定的序列化表示的责任。不幸的是,这并不能保护您免受可能的不兼容性的影响。
反序列化后,将调用定义lambda表达式的类的合成方法(与this和this answer比较),这将拒绝与lambda表达式的现有定义不匹配的反序列化尝试在该类中,匹配可能取决于lambda定义的细微方面。请注意,即使使用Eclipse而不是javac
重新编译定义类,也可能会破坏序列化兼容性。
不是security impacts of Serializable
lambdas。一般来说,我建议避免使用它。