序列化的lambda和没有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,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 但是,强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类详细信息高度敏感,这些详细信息可能因编译器实现而异,因此在反序列化期间可能会导致意外的InvalidClassExceptions。 因此,为了保证跨不同java编译器实现的一致serialVersionUID值,可序列化类必须声明显式serialVersionUID值。 强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类 – serialVersionUID字段不适用于inheritance成员。 数组类不能声明显式的serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,不需要匹配serialVersionUID值。

我该怎么办 ? 如何在Lambda中定义它?

谢谢

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

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

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

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

不是Serializable lambdas的安全影响 。 一般来说,我建议避免使用它。