У Java Enums может быть поведение?

В Java Enum может делать великие вещи, которые делают Enums, но также может иметь методы (поведение и логику). Какое преимущество имеет преимущество при использовании класса с использованием перечисления? Простые примеры, чтобы проиллюстрировать этот пункт, также приветствуются.

Ответ 1

Вот простой пример:

enum RoundingMode {
    UP {
        public double round(double d) {
            return Math.ceil(d);
        }
    },
    DOWN {
        public double round(double d) {
            return Math.floor(d);
        }
    };

    public abstract double round(double d);
}

Ответ 2

Enum также являются отличным способом реализации истинных синглетонов.

Классические одноэлементные шаблоны в Java обычно включают частные конструкторы и общедоступные статические методы factory, но все еще уязвимы для создания экземпляров посредством отражения или (дезадаптации). Тип перечисления защищает от этого.

Ответ 3

Я не совсем уверен, где заголовок вопроса подходит ко всему остальному. Да, перечисления Java имеют поведение. У них может быть и государство, хотя оно действительно должно быть действительно неизменным. (Идея изменчивого значения enum довольно страшная IMO.)

Перечисление в Java - это фиксированный набор объектов, в основном. Преимущество состоит в том, что вы знаете, что если у вас есть ссылка на этот тип, он всегда либо null, либо один из известных наборов.

Лично я действительно люблю перечисления Java и хочу, чтобы у С# их тоже - они намного объектно-ориентированные, чем перечисления С#, которые в основном являются "именованными номерами". Есть несколько "gotchas" с точки зрения порядка инициализации, но они обычно являются fab.

Ответ 4

Поскольку экземпляры перечисления являются одноточечными, вы можете использовать их в операторах switch или с помощью == для проверки равенства.

Ответ 5

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

Вы можете эмулировать "известный фиксированный набор возможных экземпляров" с обычными классами (шаблон "typafe enum", описанный в бесчисленных книгах и статьях), но это довольно некоторая работа (повторяющаяся для каждого такого класса), чтобы заставить ее работать действительно правильно в отношении сериализации, equals() и hashCode() и, возможно, некоторые другие вещи, которые я забыл. Перечисления на уровне языка избавляют вас от этой работы. И, как упоминалось выше, в операторах switch могут использоваться только перечисления уровня языка.

Ответ 6

В нашем проекте мы используем Enums для нескольких вещей, но, возможно, наиболее заметно для целей i18n - каждому изображенному тексту предоставляется Enum. Класс Enum имеет метод String-return, который проверяет используемый Locale и выбирает правильный перевод из коллекции переводов во время выполнения.

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

Использование очень просто, до такой степени, что это дает пример, но здесь, как можно использовать трансляцию-перечисление

System.out.println(Translations.GREET_PERSON.trans()+" "+user.getName());

Или, если вы хотите быть фантазией, укажите аргументы Enum accept, которые с некоторой магической строкой будут помещены в помеченную позицию в строке переводов

System.out.println(Translations.GREET_PERSON.trans(user.getName());

Ответ 7

Взгляните на классы времени java/joda, где перечисления выполняют чертовски много работы.

Вот пример java.time.Month:

public enum Month implements TemporalAccessor, TemporalAdjuster {
    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER;

    private static final Month[] ENUMS = Month.values();

    public static Month of(int month) {
        if (month < 1 || month > 12) {
            throw new DateTimeException("Invalid value for MonthOfYear: " + month);
        }
        return ENUMS[month - 1];
    }

    // About a dozen of other useful methods go here 

}