java - Utils 类中的谓词应该作为常量或静态方法提供?

标签 java guava predicate

最近,我一直在使用谓词和 Guava 实用程序。我创建了一个 Utils.class,我在其中存储了一些我在代码的不同部分使用的谓词。因此这个问题出现了,我们(我和我的同事)没有就此达成一致。

将谓词放入实用程序类中的正确方法或“良好实践方法”是什么?作为用大写字母或静态方法定义它的常量?。下面,我写一个例子:

public final class Utils {

public static final Predicate<Element> IS_SPECIAL = new Predicate<Element>() {
    @Override
    public boolean apply(Element elem) {
        return elem.special;
    }
};


public static Predicate<Element> isSpecial() {
    return new Predicate<Element>() {
        @Override
        public boolean apply(Element elem) {
        return elem.special;
    }}

顺便说一句,guava 提供了一些预定义谓词,并将它们作为返回谓词的方法提供,但其他库也提供相同的常量。

最佳答案

对此有两种观点:API 和实现。

关于 API,使用方法的解决方案比其他方法灵活得多。它允许在不关心代码的情况下更改实现,这意味着您的代码不会受到隐藏在方法后面的任何更改的影响。

关于实现,人们通常使用枚举。此处枚举相对于常量的优势有很多:

  1. 它是线程安全的。如果您使用单例变量,如果某些事情处理不当,您仍然会遇到内存问题。枚举是语言的一部分,定义将强制一致地加载每个枚举常量。
  2. 正如 rinde 在评论中提到的,枚举是可序列化的。这意味着您可以保留谓词以供进一步引用。
  3. 枚举提供了一种子命名空间。如果您想创建多个谓词,可以将它们全部定义在同一个位置,以便轻松找到它们。
  4. 枚举不会用显式子类污染代码,您不会看到 new Predicate<Element>每隔几行。然而,这种枚举的性质使得编译类中不可能有相同的枚举。所以在这里,纯粹是在源代码层面上做得更好。当然,这就是您想要的,因为您实际上是在编写源代码。

这是我将如何做的一个例子。 (是的,我什至将 Utils 重命名为 Elements ,遵循最近的 Java 默认约定)。

public final class Elements {
  private static enum ElementPredicate implements Predicate<Element> {
    SPECIAL {
      @Override public boolean apply(Element e) { return e.special; }
    }
  }

  public static Predicate<Element> isSpecial() {
    return ElementPredicate.SPECIAL;
  }

  private Elements() {}
}

最后,请注意,如果您使用的是 Java 8,则应坚持使用所提供的 lambda 机制,正如 Louis Wasserman 在问题评论中提到的那样。但是由于 lambas 在您的示例中不可用,因为您不是从方法中而是直接从字段中检索特殊信息,因此不幸的是,这个建议是无效的。然而,如果你有一个 isSpecial() Element 上的方法,然后您可以直接在代码中编写谓词,如下所示:

Stream<T> stream = ... ;
stream
    .filter(Element::isSpecial)

关于java - Utils 类中的谓词应该作为常量或静态方法提供?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35177333/

相关文章:

escaping - Guava :CharEscaper 在哪里?

java - 如果未收到数据,请发送并重试数据?

java - 在 Java 中将谓词作为 lambda 返回

java - 如何修复我的代码中的 "not a functional interface"问题

java - Bean 验证应用于接口(interface)类型

java - JLabels(和其他东西)不会显示在 JFrame(多个 JFrame)的 JPanel 内

Java堆转储和堆分析后的堆大小不同

c# - 我应该通过在我的类中注入(inject)构造函数来明确具体的类依赖关系吗?

ios - 另一个实体的核心数据过滤器

java - Spark Kryo 异常 - 类未注册 : com. google.common.base.Present