如何序列化一个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 。 方法是

  1. 修改InnerClassLambdaMetafactory始终生成序列化所需的代码
  2. 在反序列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));