gpt4 book ai didi

java - 确保函数参数可序列化的最佳方法是什么?

转载 作者:搜寻专家 更新时间:2023-10-30 20:02:11 25 4
gpt4 key购买 nike

我正在编写一个带有多个参数的可序列化类,包括一个Function:

public class Cls implements Serializable {
private final Collection<String> _coll;
private final Function<String, ?> _func;

public Cls(Collection<String> coll, Function<String, ?> func) {
_coll = coll;
_func = func;
}
}

func 存储在成员变量中,因此需要可序列化。 Java lambda are serializable if the type they're being assigned to is serializable .如果它是使用 lambda 创建的,确保我在构造函数中传递的 Function 是可序列化的最佳方法是什么?

  1. 创建一个 SerializableFunction 类型并使用它:

    public interface SerializableFunction<F, R> implements Function<F, R>, Serializable {}
    ....
    public Cls(Collection<String> coll, SerializableFunction<String, ?> func) {...}

    问题:

    • 现在 collfunc 参数不匹配,因为 func 在签名中声明为可序列化,但 coll 不是,但两者都需要可序列化才能工作。
    • 它不允许可序列化的 Function 的其他实现。
  2. 在构造函数上使用类型参数:

    public <F extends Function<String, ?> & Serializable>
    Cls(Collection<String> coll, F func) {...}

    问题:

    • 比 1 更灵活,但更困惑。
    • 两个参数之间仍然存在不匹配 - func 参数需要在编译时类型层次结构中实现 Serializable,但是 coll 只需要以某种方式 可序列化(尽管如果需要可以放弃此要求)。

    编辑当尝试使用 lambda 或方法引用调用时,此代码实际上不会编译。

  3. 留给调用者

    这需要调用者知道(从 javadoc 或反复试验)参数需要是可序列化的,并进行适当的转换:

    Cls c = new Cls(strList, (Function<String, ?> & Serializable)s -> ...);

    Cls c = new Cls(strList, (Function<String, ?> & Serializable)Foo::processStr);

    这是丑陋的 IMO,使用 lambda 的初始天真实现 保证 会被破坏,而不是像 coll 那样工作(因为大多数集合是可序列化的不知何故)。这还将类的实现细节推送给调用者。

目前我倾向于选项 2,因为它给调用者带来的负担最小,但我认为这里没有理想的解决方案。关于如何正确执行此操作的任何其他建议?

编辑:也许需要一些背景知识。这是一个在 storm 中运行的类,在一个bolt中,被序列化后转移到一个remove cluster中去执行。该函数在集群上运行时正在对已处理的元组执行操作。因此,它是可序列化的并且函数参数是可序列化的,这在很大程度上是类的目的。如果不是,则该类根本不可用。

最佳答案

在大多数情况下,答案是:不要

您可能会注意到 JRE 的大多数类,甚至是 ObjectOutputStream.writeObject不要在他们的签名中强制执行 Serializable。有太多的 API 不是专门针对序列化的,在这些 API 中,关于实现 Serializable 的对象的编译时信息会丢失,如果后者强制输入是,将它们与序列化一起使用将需要大量类型转换可序列化

由于您的参数之一是Collection,您可能会从该 API 获得示例:

Collections.unmodifiableList :

The returned list will be serializable if the specified list is serializable.

您会发现更多此类操作关心保留序列化功能,而不保留结果的Serializable 编译时类型。

这也适用于所有非public 类型,例如Collections.emptyList()Arrays.asList(…)Comparator.reverseOrder() 的结果。它们都是 Serializable 而无需声明。


此外,每个类都有更多的用例而不仅仅是序列化,应该避免强制始终Serializable。这将阻碍不涉及序列化的用途。

关于 Collection 参数,您可以考虑完全删除可序列化约束。通常,您会保护您的类(class)免受以后对您收到的集合的更改。一个简单的解决方案是复制集合,当您这样做时,您可以使用支持序列化的类型。

即使你想避免复制,序列化本身就是一个复制过程,所以你可以简单地创建自定义的 readObjectwriteObject 方法来存储 Collection 的内容,不再需要 Serializable 集合。


总而言之,通常的政策是如果您的类的用户打算序列化它的实例,则用户有责任将放入其中的所有组件本身 Serializable

关于java - 确保函数参数可序列化的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31115005/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com