序列化的lambda和没有serialVersionUID?

时间:2015-04-13 22:05:19

标签: java serialization lambda java-8 serialversionuid

我正在尝试学习序列化如何与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中定义它?

由于

1 个答案:

答案 0 :(得分:6)

serialVersionUID仅与生成stream identifier的类相关。如果可序列化类具有返回不同类的替换对象的writeReplace()方法(也在Serializable documentation中描述),则不是这种情况,因为这样的表示与原始类完全分离。这是可序列化的lambda实例所发生的情况,请参阅SerializedLambda

  

可序列化lambda的实现者,例如编译器或语言运行库,应该确保实例正确地反序列化。一种方法是确保writeReplace方法返回SerializedLambda的实例,而不是允许默认序列化继续进行。

因此,它是SerializedLambda的一个实例,最终在流上,因此该类具有稳定的序列化表示的责任。不幸的是,这并不能保护您免受可能的不兼容性的影响。

反序列化后,将调用定义lambda表达式的类的合成方法(与thisthis answer比较),这将拒绝与lambda表达式的现有定义不匹配的反序列化尝试在该类中,匹配可能取决于lambda定义的细微方面。请注意,即使使用Eclipse而不是javac重新编译定义类,也可能会破坏序列化兼容性。

不是security impacts of Serializable lambdas。一般来说,我建议避免使用它。