无法反序列化lambda

Mon*_*nad 8 java lambda serialization java-8

就像一个小项目一样,我一直试图做一个小东西,读取序列化的lambdas(本地或从FTP)并调用它们的运行函数作为测试的一部分来试验Windows中的文件关联(即打开某些文件类型)用某个程序打开它们等等,但无论我尝试什么,它似乎都没有正确地反序列化.

lambda被宣布为这样

Runnable r = (Runnable & Serializable) () -> {
    // blah blah
    // made sure not to capture anything
};
Run Code Online (Sandbox Code Playgroud)

并使用由ObjectOutputStream包装的[n optional] BufferedOutputStream包装的FileOutputStream进行序列化,没有问题.但是,当[在不同的项目中]反序列化时,它会失败,说它无法找到包含序列化代码的封闭类.我已经尝试过各种各样的东西,比如将它们包装在一个可序列化的类中(用于测试目的的是用serialVersionUID = 0L)或者定义一个扩展Runnable和Serializable的接口,但无济于事.

是的,我知道序列化lambda不是很好的做法(或者我们被告知),但我不知道如何将函数和子程序转换成我可以存储为文件或FTP的东西.如果这根本不是正确的方法,请告诉我们.

哦,我正在使用最新版本的Eclipse Luna.

编辑:

像这样反序列化

File f = new File(somePath);
FileInputStream fish = new FileInputStream(f);
BufferedInputStream bos = new BufferedInputStream(fish); // not really necessary
ObjectInputStream ois = new ObjectInputStream(bos);
Runnable r = (Runnable) ois.readObject();
ois.close();
r.run();
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 12

如果没有定义它的类,则无法反序列化对象.这与lambda表达式没有改变.

Lambda表达式有点复杂,因为它们生成的运行时类不是定义它的类,但它们的定义类是保存lambda主体代码的类,并且在可序列化lambda的情况下,是一个反序列化支持方法,用于验证并重新实例化lambda实例.

SerializedLambda:

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

SerializedLambda有一个readResolve方法,查找$deserializeLambda$(SerializedLambda)在捕获类中调用的(可能是私有的)静态方法,调用它自己作为第一个参数,并返回结果.Lambda类实现$deserializeLambda$负责验证其属性SerializedLambda是否与该类实际捕获的lambda一致.

因此,即使您的实例未在定义类中引用合成方法(例如,在对此类之外的方法的方法引用的情况下),反序列化仍然需要有$deserializeLambda$意识地验证实例的正确性.


关于序列化lambda的"良好实践",请记住lambda表达式封装了行为,而不是状态.存储行为总是意味着只存储某种引用并需要用于恢复它的代码,以实现相关的行为.如果您只是通过符号名称引用预期行为或仅存储(例如关联enum值),那么这也会起作用.

有关可序列化lambda的含义的更多信息将在此问题中进行解释.