Java 如何序列化一个 lambda?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22807912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 18:03:07  来源:igfitidea点击:

How to serialize a lambda?

javaserializationlambdajava-8

提问by assylias

How can I elegantly serialize a lambda?

如何优雅地序列化 lambda?

For example, the code below throws a NotSerializableException. How can I fix it without creating a SerializableRunnable"dummy" interface?

例如,下面的代码抛出一个NotSerializableException. 如何在不创建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();
    }
}

采纳答案by assylias

Java 8 introduces the possibility to cast an object to an intersection of types by adding multiple bounds. In the case of serialization, it is therefore possible to write:

Java 8 引入了通过添加多个边界将对象强制转换为类型交集的可能性。在序列化的情况下,因此可以编写:

Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");

And the lambda automagically becomes serializable.

并且 lambda 会自动变得可序列化。

回答by Vicente Romero

The same construction can be used for method references. For example this code:

相同的构造可用于方法引用。例如这段代码:

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

defines a lambda expression and a method reference with a serializable target type.

定义一个 lambda 表达式和一个具有可序列化目标类型的方法引用。

回答by ruediste

If you are willing to switch to another serialization framework like Kryo, you can get rid of the multiple bounds or the requirement that the implemented interface must implement Serializable. The approach is to

如果您愿意切换到另一个像Kryo这样的序列化框架,您可以摆脱多重边界或实现接口必须实现的要求Serializable。方法是

  1. Modify the InnerClassLambdaMetafactoryto always generate the code required for serialization
  2. Directly call the LambdaMetaFactoryduring deserialization
  1. 修改InnerClassLambdaMetafactory为始终生成序列化所需的代码
  2. LambdaMetaFactory在反序列化过程中直接调用

For details and code see this blog post

有关详细信息和代码,请参阅此博客文章

回答by Pascal

Very ugly cast. I prefer to define a Serializable extension to the functional interface I'm using

很丑的演员。我更喜欢为我正在使用的功能接口定义一个 Serializable 扩展

For example:

例如:

interface SerializableFunction<T,R> extends Function<T,R>, Serializable {}
interface SerializableConsumer<T> extends Consumer<T>, Serializable {}

then the method accepting the lambda can be defined as such :

那么接受 lambda 的方法可以定义为:

private void someFunction(SerializableFunction<String, Object> function) {
   ...
}

and calling the function you can pass your lambda without any ugly cast:

并调用该函数,您可以在没有任何丑陋演员的情况下传递 lambda:

someFunction(arg -> doXYZ(arg));

回答by Rafa?l

In case someone falls here while creating Beam/Dataflow code :

万一有人在创建 Beam/Dataflow 代码时跌倒在这里:

Beam has his own SerializableFunctionInterface so no need for dummy interface or verbose casts.

Beam 有自己的SerializableFunction接口,因此不需要虚拟接口或冗长的强制转换。