java - является - регулярные выражения. 3-е изд.




Это хорошая практика использовать порядковый номер перечисления? (6)

Во-первых, вам, вероятно, даже не нужно числовое значение порядка - для этого и предназначен Enum<E> , а Enum<E> реализует Comparable<E> .

Если вам по какой-то причине нужно числовое значение заказа, то да, вы должны использовать ordinal() . Вот для чего это.

Стандартной практикой для Java Enums является сортировка по порядку объявления, поэтому Enum<E> реализует Comparable<E> и почему Enum.compareTo() является final .

Если вы добавите свой собственный нестандартный код сравнения, который не использует Comparable и не зависит от порядка объявления, вы просто запутаете любого, кто попытается использовать ваш код, в том числе и себя самого в будущем. Никто не будет ожидать, что этот код будет существовать; они ожидают, что Enum будет Enum .

Если пользовательский заказ не соответствует порядку декларации, любой, кто просматривает декларацию, будет сбит с толку. Если он (случается, в данный момент) соответствует порядку декларации, любой, кто смотрит на него, будет ожидать этого, и у него будет неприятный шок, когда в будущем он этого не сделает. (Если вы пишете код (или тесты), чтобы убедиться, что пользовательский порядок соответствует порядку объявления, вы просто подчеркиваете, насколько он не нужен.)

Если вы добавляете свою собственную стоимость заказа, вы создаете головные боли для обслуживания:

  1. вам нужно убедиться, что ваши значения hierarchy являются уникальными
  2. если вы добавляете значение в середине, вам нужно перенумеровать все последующие значения

Если вы беспокоитесь, что кто-то может случайно изменить порядок в будущем, напишите модульный тест, который проверяет порядок.

В итоге, в бессмертных словах Статьи 47 : знай и используй библиотеки .

PS Кроме того, не используйте Integer когда вы имеете в виду int . 🙂

У меня есть enum:

public enum Persons {

    CHILD,
    PARENT,
    GRANDPARENT;

}

Есть ли проблемы с использованием метода ordinal() для проверки "иерархии" между членами перечисления? Я имею в виду - есть ли недостатки при его использовании, исключая многословие, когда кто-то может случайно изменить порядок в будущем.

Или лучше сделать что-то подобное:

public enum Persons {

    CHILD(0),
    PARENT(1),
    GRANDPARENT(2);

    private Integer hierarchy;

    private Persons(final Integer hierarchy) {
        this.hierarchy = hierarchy;
    }

    public Integer getHierarchy() {
        return hierarchy;
    }

}

Если вы ссылаетесь на javadoc для ordinal метода в Enum.java :

Большинство программистов не будут использовать этот метод. Он разработан для использования сложными структурами данных на основе перечислений, такими как java.util.EnumSet и java.util.EnumMap .

Во-первых - прочитайте руководство (в данном случае javadoc).

Во-вторых - не пишите хрупкий код. Значения enum могут измениться в будущем, и ваш второй пример кода станет более понятным и понятным .

Вы определенно не хотите создавать проблемы на будущее, если, скажем, новое значение enum вставлено между PARENT и GRANDPARENT .


Использование ordinal() не рекомендуется, поскольку изменения в объявлении enum могут повлиять на порядковые значения.

ОБНОВИТЬ:

Стоит отметить, что поля перечисления являются константами и могут иметь дублированные значения, т.е.

enum Family {
    OFFSPRING(0),
    PARENT(1),
    GRANDPARENT(2),
    SIBLING(3),
    COUSING(4),
    UNCLE(4),
    AUNT(4);

    private final int hierarchy;

    private Family(int hierarchy) {
        this.hierarchy = hierarchy;
    }

    public int getHierarchy() {
        return hierarchy;
    }
}

В зависимости от того, что вы планируете делать с hierarchy это может быть либо разрушительным, либо полезным.

Кроме того, вы можете использовать константы enum для создания своих собственных EnumFlags вместо использования EnumSet , например


Как предложил Джошуа Блох из Effective Java , не следует извлекать значение, связанное с перечислением, из его порядкового номера, потому что изменения в порядке значений перечисления могут нарушить логику, которую вы кодировали.

Второй подход, о котором вы упомянули, в точности соответствует тому, что предлагает автор: хранение значения в отдельном поле.

Я бы сказал, что предложенная вами альтернатива, безусловно, лучше, потому что она более расширяемая и обслуживаемая, поскольку вы разделяете порядок значений перечисления и понятие иерархии.


Это не прямой ответ на ваш вопрос. Скорее лучший подход для вашего варианта использования. Этот способ гарантирует, что следующий разработчик будет явно знать, что значения, присвоенные свойствам, не должны изменяться.

Создайте класс со статическими свойствами, которые будут имитировать ваше перечисление:

public class Persons {
    final public static int CHILD = 0;
    final public static int PARENT = 1;
    final public static int GRANDPARENT = 2;
}

Затем используйте как enum:

Persons.CHILD

Это будет работать для большинства простых случаев использования. В противном случае у вас могут отсутствовать такие параметры, как valueOf() , EnumSet , EnumSet или values() .


Я бы использовал ваш второй вариант (используя явное целое число), чтобы числовые значения назначались вами, а не Java.







verbose