定义谓词和函数的正确方法

Correct way to define Predicates and Functions

定义Predicate's or Function时,我曾经将它们创建为static final

private static final Predicate<SomeDto> SOME_PREDICATE =
                new Predicate<SomeDto>() {
                    @Override
                    public boolean apply(SomeDto input) {
                        return input.isValid();
                    }
                }

但是我注意到 enum 版本也有很多用途,例如

private enum SomePredicate implements Predicate<SomeDto> {
        INSTANCE;

        @Override
        public boolean apply(SomeDto input) {
            return input.isValid();
        }
    }

我知道 enum vs static final 主题,但是使用枚举相对于带有谓词或函数的 static final 有什么真正的优势吗?

两种方法都不比另一种更正确。

如果您在 What's the advantage of a Java enum versus a class with public static final fields? 阅读了之前的回答,您会发现枚举方法的优点是可以轻松迭代枚举的所有可能值。但是,在您的情况下,您只有一个可能的值,因此这不是一个好处。

基于枚举的方法的一个优点是您的 class 将有一个更漂亮的名称和一个您可以选择的名称。如果您想打印 class 的名称,这可能是一个决定性因素。

在这种情况下,enum 单例方法的主要优点是 Predicate/Function 自动 Serializable

出于这个原因,Guava 本身在其某些 PredicateFunction 实现中使用 enums,等等。 Josh Bloch 建议在 Effective Java 第二版 Item 3 中想要单例时使用 enums。引用:

This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

不过,Guava 在其 API 中通过静态方法公开了这些单例,避免了用户代码中 SomePredicate.INSTANCE 的丑陋。