无法反序列化lambda [英] Unable to deserialize lambda

查看:196
本文介绍了无法反序列化lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Just as a small project, I've been trying to make a wee thing that reads serialized lambdas (locally or from an FTP) and invokes their run functions as part of a test to experiment with file associations in Windows (i.e. opening certain file types opens them with a certain program) and whatnot, but no matter what I try, it never seems to properly deserialize.

lambda声明如此

The lambda was declared like so

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

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

and serialized using a FileOutputStream wrapped by a[n optional] BufferedOutputStream wrapped by an ObjectOutputStream without issue. However, when deserialized [in a different project], it fails, saying that it could not find the enclosing class that contained the code for serializing it. I've tried various things like wrapping them in a serializable class (w/serialVersionUID = 0L for testing purposes) or defining a an interface that extends Runnable and Serializable, but to no avail.

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

Yes, I am aware that serializing lambdas isn't really good practice (or so we're told), but I'm not sure how to go about turning functions and subroutines into something I can store as a file or in an FTP. If this isn't even the right way at all, do tell.

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

Oh, I'm using Eclipse Luna of whatever the latest version is.

修改:

反序列化

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();


推荐答案

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

You can’t deserialize an object without the class defining it. This hasn’t changed with lambda expressions.

Lambda表达式有点复杂,因为它们生成的运行时类不是定义它的类,但它们的定义类是一个持有lambda主体的代码,如果是可序列化的lambda,则调用反序列化支持方法,该方法用于验证和重新实例化lambda实例。

Lambda expressions are a bit more complex as their generated runtime class is not the class which defined it but their defining class is the one holding the code of the lambda’s body and, in case of serializable lambdas, a deserialization support method which is called for validating and re- instantiating the lambda instance.

参见 SerializedLambda


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

Implementors of serializable lambdas, such as compilers or language runtime libraries, are expected to ensure that instances deserialize properly. One means to do so is to ensure that the writeReplace method returns an instance of SerializedLambda, rather than allowing default serialization to proceed.

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

SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument, and returns the result. Lambda classes implementing $deserializeLambda$ are responsible for validating that the properties of the SerializedLambda are consistent with a lambda actually captured by that class.

所以即使你的实例没有在定义类中引用合成方法(例如在方法的情况下)引用此类之外的方法),反序列化仍然需要 $ deserializeLambda $ 来故意验证实例的正确性。

So even if your instance was not referring to a synthetic method inside the defining class (e.g. in the case of a method reference to a method outside this class), deserialization still requires the $deserializeLambda$ for validating the correctness of the instance, intentionally.

关于序列化lambda的好习惯,请记住lambda表达式封装了行为,而不是状态。存储行为总是意味着只存储某种引用并需要用于恢复它的代码,以实现相关的行为。如果您只是通过符号名称引用预期的行为或者只是存储,例如存储,那也可以。关联的枚举值。

Regarding the "good practice" of serializing lambdas, keep in mind that lambda expressions encapsulate behavior, not state. Storing behavior always implies storing just some kind of reference and requiring the code intended to restore it, to have implemented the associated behavior. That would work as well if you just referred to the intended behavior by a symbolic name or just stored, e.g. associated enum values.

有关可序列化lambda的含义的更多信息,请参阅这个问题

More about the implications of having serializable lambdas is explained in this question.

这篇关于无法反序列化lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆