Лучшая практика Java Enum property

#java #enums #enumeration

#java #перечисления #перечисление

Вопрос:

Я видел два подхода к обработке перечислений со свойствами. Одно лучше другого?

Как свойство:

 public enum SEARCH_ENGINE {
    GOOGLE("http://www.google.com"),
    BING("http://www.bing.com");

    private final String url;

    private SEARCH_ENGINE(String url) {
        this.url = url;
    }

    public String getURL() {
        return url;
    }
}
  

В качестве метода:

 public enum SEARCH_ENGINE {
    GOOGLE {
        public String getURL() {return "http://www.google.com";}
    },
    BING {
        public String getURL() {return "http://www.bing.com";}
    };

    public abstract String getURL();
}
  

Комментарии:

1. Действительно ли компилируется второй вариант? Похоже, что он создает отдельные классы для каждой константы перечисления (это единственный способ, которым вы могли бы переопределить getURL(). Первое, безусловно, лучше.

2. Лично мне больше нравится второе. Это более гибко. Но по сути они делают то же самое.

3. @mellamokb — поведение может быть таким же. То, как это преобразуется в байт-код и выполняется, сильно отличается (и да, отвечая на мой предыдущий вопрос, это компилируется и создает анонимные подклассы)

4. Я всегда использую первое. Я никогда не использовал второй метод для создания перечислений.

5. @JustinKSU: Ну, это означает, что JIT с меньшей вероятностью сможет встроить его. Я думаю, что шансы на то, что это будет значительным, в значительной степени равны нулю.

Ответ №1:

Первый явно выглядит более чистым для меня — он использует общность, заключающуюся в том, что каждый элемент перечисления будет иметь URL-адрес с фиксированной строкой, который известен при инициализации. Вы фактически повторяете эту «логику» в каждой реализации во второй версии. Вы переопределяете метод, чтобы обеспечить ту же логику («просто возвращайте строку, которая известна во время компиляции») в каждом случае. Я предпочитаю резервировать переопределение для изменений в поведении.

Я предлагаю сделать url поле закрытым, хотя в первом.

Комментарии:

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

2. 1. url является частным … 2. Недостатком этого подхода, который я вижу, является то, что существует несколько правил приличия. Приятно видеть значение рядом со свойством, с которым связано, вместо того, чтобы проверять конструктор.

3. @JustinKSU: Да, это частное и, безусловно, должно быть — но ИМО оно должно также быть окончательным.

Ответ №2:

Взгляните на пункт 21 из этой главы книги Джоша Блоха «Эффективная Java». В нем говорится о типобезопасном шаблоне перечисления.

Комментарии:

1. Эта глава, похоже, посвящена тому, как реализовать перечисления с классами до JDK 1.5

Ответ №3:

Я бы выбрал первое, поскольку компилятор жалуется, если вы каким-то образом забываете добавить URL. Второе позволило бы вам здесь допускать ошибки.

Комментарии:

1. При втором подходе компилятор будет жаловаться, если вы не переопределите метод getURL(), достигающий той же цели.

2. Во втором компилятор тоже жалуется: <anonymous SEARCH_ENGINE$2> is not abstract and does not override abstract method getURL() in SEARCH_ENGINE .