Синглтон функционального интерфейса Java как перечисление
Рассматривая исходный код класса 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();
}
}
//...
}
Я думаю, я понимаю, что это делает. Это экземпляр Singleton, который реализует интерфейс Comparator. Он использует "compareTo" классов, которые реализуют интерфейс Comparable для естественного упорядочения (пожалуйста, поправьте меня, если я ошибаюсь в этом).
Однако я не понимаю, почему это делается с использованием перечисления. Мне очень нравятся перечисления для Singletons, не поймите меня неправильно, но в этом случае я лично думаю, что это было бы проще:
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_COMPARATOR
, когда вы пишете объект и читаете его, будет создан новый NATURAL_ORDER_COMPARATOR
. Поскольку стоимость объекта настолько мала, что он обрывает синглтон.
Некоторыми доказательствами для этого являются Collections.ReverseComparator
. Он использует ваш подход:
static final ReverseComparator REVERSE_ORDER = new ReverseComparator();
Но недостатком является то, что для поддержания синглтона должен присутствовать следующий код
private Object readResolve() { return Collections.reverseOrder(); }
Теперь, какой из них проще? Лично я предпочитаю использовать шаблон "enum singleton" в качестве своего первого выбора.
Ответ 2
Это точно так же, как в пункте 89: например, управление, предпочитайте типы перечислений для чтенияResolve из Effective Java на самом деле и это связано с Serialization
.
Поддержание readResolve
вместо экземпляра enum намного сложнее и громоздко.