如何序列化一个lambda?
我如何优雅地序列化一个lambda?
例如,下面的代码会抛出一个NotSerializableException
。 我怎样才能修复它,而不创build一个SerializableRunnable
“虚拟”接口?
public static void main(String[] args) throws Exception { File file = Files.createTempFile("lambda", "ser").toFile(); try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(file))) { Runnable r = () -> System.out.println("Can I be serialized?"); oo.writeObject(r); } try (ObjectInput oi = new ObjectInputStream(new FileInputStream(file))) { Runnable r = (Runnable) oi.readObject(); r.run(); } }
Java 8引入了通过添加多个边界来将对象投射到types交集的可能性。 在序列化的情况下,可以这样写:
Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");
lambda自动成为可串行化的。
相同的构造可以用于方法参考。 例如这个代码:
import java.io.Serializable; public class Test { static Object bar(String s) { return "make serializable"; } void m () { SAM s1 = (SAM & Serializable) Test::bar; SAM s2 = (SAM & Serializable) t -> "make serializable"; } interface SAM { Object action(String s); } }
用一个可序列化的目标types定义一个lambdaexpression式和一个方法引用。
如果您愿意切换到另一个序列化框架(如Kryo) ,则可以摆脱多重边界或实现的接口必须实现Serializable
。 方法是
- 修改
InnerClassLambdaMetafactory
始终生成序列化所需的代码 - 在反序列
LambdaMetaFactory
过程中直接调用LambdaMetaFactory
有关详情和代码,请参阅此博客文章
非常丑陋的演员。 我更喜欢为我正在使用的function接口定义一个Serializable扩展
例如:
interface SerializableFunction<T,R> extends Function<T,R>, Serializable {} interface SerializableConsumer<T> extends Consumer<T>, Serializable {}
那么接受lambda的方法可以这样定义:
private void someFunction(SerializableFunction<String, Object> function) { ... }
并调用函数,你可以传递你的lambda没有任何丑陋的演员:
someFunction(arg -> doXYZ(arg));