Enum values ​​(). Length vs private field

У меня есть перечисление вроде этого:

public enum Configuration {
    XML(1),
    XSLT(10),
    TXT(100),
    HTML(2),
    DB(20);

    private final int id;
    private Configuration(int id) {
        this.id = id;
    }
    public int getId() { return id; }
}

Иногда мне нужно проверить, сколько полей у меня есть в перечислении. Какое лучшее решение? Должен ли я использовать метод "values ​​(). Length"? Или, может быть, я должен создать постоянное поле в перечислении следующим образом:

public enum Configuration {
    XML(1),
    XSLT(10),
    TXT(100),
    HTML(2),
    DB(20);

    private final int id;
    private Configuration(int id) {
        this.id = id;
    }
    public int getId() { return id; }

    public static final int Size = 5;
}

Какое самое быстрое и элегантное решение?

Ответ 1

Использование values().length будет создавать новую копию массива каждый раз, когда вы его вызываете. Иногда я создаю свой собственный List (или устанавливаю, или карту, что мне нужно), чтобы избежать этого бессмысленного копирования. Я бы не жестко его кодировал, хотя... если вам нужен только размер, я бы просто использовал:

private static final int size = Configuration.values().length;

в конце. К моменту оценки все значения будут инициализированы. Это позволяет избежать проблем СУХОЙ и непоследовательности, возникающих в других ответах.

Конечно, это немного микро-оптимизация сама по себе... но одна из которых заканчивается более простым кодом в конце, IMO. Вызов values().length из другого источника не выражает то, что вас интересует, это просто размер перечисления - тот факт, что вы получаете его через массив значений, является случайным и отвлекающим, IMO.

Альтернативой использованию values() является использование EnumSet.allOf().size(), который для небольших перечислений будет довольно дешевым - но опять же, он не так читается, как просто имеет поле size.

Ответ 2

Я бы рекомендовал использовать values().length. Это намного более изящно, а производительность накладных расходов по сравнению с использованием константы будет небрежной. Кроме того, вы устраняете риск того, что постоянный постоянно выходит из строя с фактической длиной перечисления.

Ответ 3

Сохраняя счет, вы нарушаете принцип DRY, поэтому, если у вас нет веских оснований, вы не должны.

Ответ 4

Другой подход - использовать константу, инициализированную поверх метода values ​​().

public enum Colors {
    BLUE, GREEN, FUCHSIA;
    public static int COUNT = Colors.values().length;
}

Таким образом, у вас есть автоматически обновляемая константа и все же избегайте использования служебных данных "values ​​()".