Java功能接口的单例作为枚举

2022-09-04 08:26:36

在查看 Comparators 类的源代码时,我遇到了这些代码行。

class Comparators {

    //...

    enum NaturalOrderComparator implements Comparator<Comparable<Object>> {
        INSTANCE;

        @Override
        public int compare(Comparable<Object> c1, Comparable<Object> c2) {
            return c1.compareTo(c2);
        }

        @Override
        public Comparator<Comparable<Object>> reversed() {
            return Comparator.reverseOrder();
        }
    }

    //...

}

我想我明白这是做什么的。它是一个实现比较器接口的单例实例。它使用实现Compable接口的类的“compareTo”进行自然排序(如果我在其中任何一个方面都错了,请纠正我)。

然而,我不明白的是,为什么它是用枚举完成的。我真的很喜欢单例的枚举,不要误会我的意思,但在这种情况下,我个人认为这会更简单:

public static final Comparator<Comparable<Object>> NATURAL_ORDER_COMPARATOR =
    new Comparator<Comparable<Object>>() {
        @Override
        public int compare(Comparable<Object> c1, Comparable<Object> c2) {
            return c1.compareTo(c2);
        }

        //...

    }

除了个人偏好之外,还有什么理由使用枚举来实现这一点吗?


答案 1

这可能是由于.Serializable

根据您的方法,如果创建一个对象,该对象在写入对象并将其读回时保存 ,则将创建一个新的对象。由于对象成本非常小,因此会破坏单例Comparators.NATURAL_ORDER_COMPARATORNATURAL_ORDER_COMPARATOR

一些证据是。它使用您的方法:Collections.ReverseComparator

static final ReverseComparator REVERSE_ORDER = new ReverseComparator();

但缺点是必须存在以下代码才能维护单例

private Object readResolve() { return Collections.reverseOrder(); }

现在哪一个更容易?就个人而言,我更喜欢使用“枚举单例”模式作为我的首选。


答案 2

这正是第89项中的要点:例如,控件,更喜欢枚举类型来读取实际上从有效Java解析,这与有关。Serialization

维护而不是枚举实例要复杂得多,也麻烦得多。readResolve


推荐