当前位置: 首页 > 知识库问答 >
问题:

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

顾宣
2023-03-14

我正在编写一个可序列化的类,它接受多个参数,包括一个函数:

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存储在成员变量中,因此需要可序列化。如果分配给它们的类型是可序列化的,则Javalambda是可序列化的。如果使用lambda创建Function,那么确保在构造函数中传递的Function是可序列化的最佳方法是什么?

>

  • 创建一个可序列化函数,并使用该函数:

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

    问题:

    • 现在,coll和func参数之间不匹配,因为func在签名中声明为可序列化,但不是,但两者都需要可序列化才能工作
    • 它不允许其他可序列化的函数实现

    在构造函数上使用类型参数:

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

    问题:

    • 比1更灵活,但更容易混淆
    • 这两个参数之间仍然不匹配-在编译时类型继承机制中实现可串行化需要func参数,但只需要以某种方式实现可串行化(虽然如果需要,可以放弃此要求)

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

    把它留给打电话的人

    这要求调用者(从javadocs或试错)知道参数需要可序列化,并根据需要进行强制转换:

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

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

    在我看来,这很难看,使用lambda的最初天真实现肯定会失败,而不太可能与coll一起工作(因为大多数集合都是可以序列化的)。这还将类的实现细节推送到调用方。

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

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


  • 共有1个答案

    阎晔
    2023-03-14
    匿名用户

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

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

    由于其中一个参数是集合,因此您可以从该API获得示例:

    Collections.unmodifiable列表:

    如果指定的列表可序列化,则返回的列表将可序列化。

    您将发现更多这样的操作,它们关心保留序列化功能,而不保留结果上的可序列化编译时类型。

    这也适用于所有非公共类型,例如收集的结果。emptyList(),数组。asList(…)和比较器。反转顺序()。它们都是可序列化的,无需声明。

    此外,每个用例多于序列化的类都应该避免强制总是可序列化的。这将妨碍在不涉及序列化的情况下使用。

    关于集合参数,您可以考虑完全删除可序列化约束。通常,您可以保护您的类不受稍后对所接收集合的更改的影响。一个简单的解决方案是复制集合,在执行此操作时,可以使用支持序列化的类型。

    即使您希望避免复制,序列化本身也是一个复制过程,因此您只需创建存储集合内容的自定义读取对象(readObject)和写入对象(writeObject)方法,就不需要具有可序列化的集合。

    概括地说,通常的策略是,如果类的用户打算序列化它的实例,那么用户有责任让放入其中的所有组件本身都是可序列化的。

     类似资料:
    • 问题内容: Python方法返回给定对象的元组。有相应的逆函数吗?如果不是,是否有一种简单的方法来计算给定的年份,星期数和星期几? 问题答案: Python 3.8添加了fromisocalendar()方法: Python的3.6添加的,并指示: 原始答案 我最近不得不自己解决此问题,并提出了以下解决方案: 一些测试用例:

    • 问题内容: 说我有一个查询表格 我想参数化in。 有没有一种简单的方法可以在Java中使用JDBC进行操作,而该方法可以在多个数据库上运行而无需修改SQL本身? 我发现的最接近的问题与C#有关,我想知道Java / JDBC是否有所不同。 问题答案: 在JDBC中,确实没有直接的方法可以做到这一点。某些 JDBC驱动程序似乎支持该IN子句。我只是不确定那是哪个。 你可以仅使用带有和的辅助方法,并为

    • 问题内容: 当我将WCF配置为使用jSON序列化并将DataTable包含在我的一个DataContracts中时,它会先将DataTable序列化为XML,然后再将整个DataContract序列化为jSON。我希望将DataTable序列化为jSON,而不是XML。 我的问题是: 为什么首先将DataTable序列化为XML? 我如何才能将其序列化到jSON? 问题答案: DataTable是

    • 问题内容: 我上了一堂课,想跟踪学生的统计数据。我打算稍后制作一个GUI来处理这些数据。 我的主要问题是:保存和以后检索此数据的最佳方法是什么? 我已经读过关于pickle和JSON的文章,但是我并没有真正了解它们的工作方式(尤其是关于它们如何保存数据的信息,例如哪种格式和位置)。 问题答案: 对于持久性数据(存储有关学生的信息),数据库是一个不错的选择。如前所述,Python附带了Sqlite3

    • 我需要从数据库中选择一百个参数,然后在d to返回它来创建一个excel文件。 我使用的是spring数据,我认为有两种解决方案: > 使用multiselect方法,然后在DTO中定义一个包含所有参数的构造函数(参数数大于100) 使用multiselect方法并将数组(Object[])映射到DTO= 请问你还有其他的想法吗? 谢谢。

    • 问题内容: 已关闭 。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑此帖子来关注一个问题。 12个月前关闭。 改善这个问题 什么是 最简单的 , tersest ,最 灵活的 方法或库解析Python的命令行参数? 问题答案: 该答案表明哪种方法适用于较旧的Python版本。对于Python 2.7及更高版本,请替换。有关更多信息,请参见此答案。 正如其他人