Lambda表达式的序列化

3

我正在研究Java序列化的lambda表达式。

我有两个完全独立的项目,它们各自拥有一个类。

项目1:

class TestMain {

    public static void main(String[] args) {
        Runnable r = (Runnable & Serializable) () -> {};

        // Serialize r to C:/file.ser;
    }
}

项目2:

class TestMain2 {

    public static void main(String[] args) {
        // Deserialize C:/file.ser to runnable;
    }
}

然而,在尝试反序列化可运行的程序时,它会抛出一个异常,说找不到TestMain

...有没有什么方法可以避免这种情况?


整体来说不是一个好主意。不要这样做。 - iced
2个回答

5
解决方法是在反序列化时将 TestMain 包含在类路径中。
Lambda 表达式隐式依赖于声明它的外部类。
此外,Java 教程 还表示:

但是,与内部类一样,强烈不建议序列化 Lambda 表达式。


此外,正如 @Tim 指出的那样,即使您不需要 TestMain.class 文件,仍然需要包含包含 Lambda 代码的 TestMain$xxx.class 文件。

1
糟糕,这回答了我的问题,只是不是我想要的答案 :p - Cheetah

2
...is there any way I can avoid this?

总的来说,不行

序列化是一种用于持久化数据而非代码的方法。在反序列化时,被序列化类的代码需要存在于执行反序列化操作的JVM内部。

看起来你在尝试在两个JVM之间传递代码。
虽然有一些技巧可以做到这一点,但不能通过序列化实现。


1
有一些简单的机制,比如定义/使用表达式语言,这样你只需要传递字符串:MVEL、OGNL、Spring EL、JBoss EL 中的任何一个都可以为你工作。更复杂的方法是实际传递真正的 Java 代码,这将需要使用自定义类加载器,可能与 asm 或 cglib 等字节码库结合使用。 - Tim
1
@Cheetah: 如果你不想要TestMain的依赖项,请在一个没有这些依赖项的类中声明lambda函数。 - Holger
@Holger - 我无法控制这个......这是为客户库而设计的。 - Cheetah
@Cheetah:但是你可以控制以确保你想序列化的对象是可序列化的lambda表达式? - Holger
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Cheetah
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接