lambda创建后的序列化

ass*_*ias 13 java lambda serialization java-8

我可以使用以下语法序列化lambda:

Runnable r = (Runnable & Serializable) () -> System.out.println("");
try (ObjectOutput oo = new ObjectOutputStream(new ByteArrayOutputStream())) {
  oo.writeObject(r);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我从客户端代码收到lambda并且它没有被正确转换,我就无法序列化它.

如何r在不更改其定义的情况下序列化以下内容:

Runnable r = () -> System.out.println("");
Run Code Online (Sandbox Code Playgroud)

我试图序列化"派生"对象:

Runnable r1 = (Runnable & Serializable) r::run;
Runnable r2 = (Runnable & Serializable) () -> r.run();
Run Code Online (Sandbox Code Playgroud)

但在每种情况下,都oo.writeObject(rxxx);失败了NotSerializableException.

Bri*_*etz 15

这是正确的,并且是设计的.正如您无法在实例化后获取非可序列化对象并使其可序列化一样,一旦创建了lambda,就会设置其可序列化.

如果lambda的目标类型是可序列化的(并且其捕获的参数是可序列化的),则lambda是可序列化的.您的第一个示例是可序列化的,因为目标类型是交集(Runnable&Serializable).您的两次转换尝试r失败,因为在两种情况下,r都是一个不可序列化的捕获变量,因此生成的lambda表达式/方法引用不可序列化.(绑定方法引用的接收器充当捕获变量.)

  • 如果目标类型已经是"可序列化",那么如何"洗掉"可序列化标记?除非我使用不同的目标类型,否则每次重新包装在另一个lambda中将再次创建一个`Serializable` lambda.但如果我能够使用不同的目标类型,我首先就没有问题.我可以强行添加一个捕获的非"可串联"值,但仍然必须非常小心地完成,以防止使用精心设计的序列化形式进行攻击.并且它不允许摆脱可序列化lambda的开销. (2认同)