确保函数参数可序列化的最佳方法是什么?
我正在编写一个可序列化的类,它接受几个参数,包括: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 lambdas 被分配到的类型是可序列化的,那么它们是可序列化的。如果 I 在构造函数中传递是可序列化的,如果它是使用 lambda 创建的,那么确保 I 在构造函数中传递的最佳方法是什么?Function
-
创建一个类型并使用:
SerializableFunction
public interface SerializableFunction<F, R> implements Function<F, R>, Serializable {} .... public Cls(Collection<String> coll, SerializableFunction<String, ?> func) {...}
问题:
- 现在,和 参数之间存在不匹配,因为在签名中声明为可序列化,但不是,但两者都需要可序列化才能正常工作。
coll
func
func
coll
- 它不允许其他可序列化的实现。
Function
- 现在,和 参数之间存在不匹配,因为在签名中声明为可序列化,但不是,但两者都需要可序列化才能正常工作。
-
在构造函数上使用类型参数:
public <F extends Function<String, ?> & Serializable> Cls(Collection<String> coll, F func) {...}
问题:
- 比1更灵活,但更令人困惑。
- 这两个参数之间仍然存在不匹配 - 该参数需要在编译时类型层次结构中实现,但只需要以某种方式进行序列化(尽管如果需要,可以丢弃此要求)。
func
Serializable
coll
编辑尝试使用 lambda 或方法引用进行调用时,此代码实际上不会编译。
-
留给呼叫者
这要求调用方知道(来自javadocs或试错法)参数需要可序列化,并根据需要强制转换:
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 群集以执行。在集群上运行时,该函数正在对已处理的元组执行操作。因此,该类的用途的很大一部分是它是可序列化的,并且函数参数是可序列化的。如果不是,则该类根本不可用。