【问题标题】:Java Rich Enum Types: Specifying Constant-Specific Behavior With Function Objects vs. Constant Specific MethodsJava 富枚举类型:使用函数对象指定特定于常量的行为与特定于常量的方法
【发布时间】:2013-08-02 13:29:28
【问题描述】:

在 Java 中,函数对象是无状态对象的实例(通常是实现策略接口的单例),其方法对其他对象的状态进行操作。这些是 Java 的等价物,相当于将函数指针作为参数传递给方法,就像在 C 等语言中所做的那样。

1.5 中引入的 Java 枚举规范使程序员能够通过将策略“接口”指定为枚举声明中的一系列抽象方法声明来复制函数对象模式,然后必须为每个枚举常量实现这些声明。

因此,如果要将特定于常量的行为与枚举常量相关联,至少有两种选择:

  • 您可以先声明Enum implement 您的策略接口,然后将行为作为函数对象存储在最终的enum 实例字段中。然后,客户端代码可以通过 enum 字段访问器方法调用该行为。

  • 您可以在Enum 声明中将“策略”声明为一个或多个abstract 方法。编译器会坚持为每个enum 常量实现这些。然后,客户端代码可以通过enum 常量直接调用该方法来调用该行为。

在我看来,函数对象方法需要更多资源。需要在堆上分配对象,对于大型枚举,这可能是几个对象。通过访问器调用的需求似乎需要更慢的执行速度,但是我猜现代 JVM 实现会足够聪明,可以内联方法调用,从而使两种模式的执行速度相似。

我目前使用函数对象来为我编写的 JDBC 数据库应用程序指定“动态”元数据。这些对象描述了数据库的某些特性,例如列和行不变量、用于创建与枚举类对应的数据模型对象的工厂、用于获取和改变数据模型对象数据的访问器以及其他类似的元数据。

这种方法确实需要大量样板文件。很多样板。

虽然使用特定于常量的方法并不能保证消除样板文件,但这种方法应该更简洁易读......并且可能更有效。

我应该重构我的枚举设计以使用特定于常量的方法来代替函数对象吗?

【问题讨论】:

  • +1 个问题,但您应该了解所查看的每件事的延迟规模,并首先优化最大的延迟。
  • 当我的策略集未关闭时,我使用枚举的“函数对象”方法;枚举提供了“众所周知的”策略,但策略消费者是针对接口编写的,如果需要,客户端可以实现自己的策略,而不是使用众所周知的策略之一。如果无法实现新策略,则接口没有任何作用,您应该为每个枚举使用特定于常量的实现。
  • @erickson:这真是一个绝妙的建议。谢谢你。

标签: java methods enums


【解决方案1】:

我应该重构我的枚举设计以使用特定于常量的方法来代替函数对象吗?

如果您关心 enum 方法调用的性能和额外的引用成本(最多 10 纳秒),那么您根本不应该在关键路径中使用数据库。数据库访问通常为 10,000,000 纳秒。即使是您已经拥有的查询的行访问也可以是 10,000 纳秒。 Java Chronicle 被设计为超轻量级、少 GC、无锁、低系统调用、数据持久性,甚至可以在 100 到 500 纳秒的数量级内持久化并重新读取一些较大的业务对象。

简而言之,您必须弄清楚什么规模对您来说很重要,并首先开始优化掉最大的击球手。这意味着使用商业分析器对您的应用程序进行分析,当分析器放弃并说您没有创建任何垃圾并且没有使用任何 CPU 或访问任何数据库时,您才应该开始担心成本解引用和使用对象来保存函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多