Перечисления Java по сравнению со статическими константами

Я смотрю на некоторый код Java, которые сохраняются другими частями компании, случайно некоторый прежний C и C++ devs. Одной вещью, которая повсеместна, является использование статических целочисленных констант, такой как

class Engine {
    private static int ENGINE_IDLE = 0;
    private static int ENGINE_COLLECTING = 1;
    ...
}

Помимо недостающего 'заключительного' спецификатора, я немного побеспокоен этим видом кода. То, что мне понравилось бы видеть, будучи обученным, прежде всего, в Java из школы, будет чем-то больше как

class Engine {
    private enum State { Idle, Collecting };
    ...
}

Однако аргументы приводят меня к сбою. Да ведь если вообще, последний лучше, чем первый?

20
задан Christoffer 9 February 2010 в 13:22
поделиться

9 ответов

Почему, если вообще, второй вариант лучше. чем первый?

Он намного лучше, потому что обеспечивает безопасность типов и самодокументируется. При использовании целочисленных констант вам придется обратиться к документации API, чтобы узнать, какие значения являются допустимыми, и ничто не помешает вам использовать недопустимые значения (или, что еще хуже, целочисленные константы, которые совершенно не связаны между собой). В случае с Enums сигнатура метода прямо говорит вам, какие значения являются допустимыми (автозавершение в IDE будет работать), и невозможно использовать недопустимое значение.

Шаблон "integer constant enums", к сожалению, очень распространен, даже в Java Standard API (и широко скопирован оттуда), потому что в Java не было Enums до Java 5.

24
ответ дан 29 November 2019 в 23:27
поделиться

Выдержка из официальных документов, http://java.sun.com/j2se/1.5.0/docs/guide/language/ enums.html :

Этот шаблон имеет много проблем, таких как:

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

И это почти все. Аргументом из одного слова было бы то, что перечисления просто более читабельны и информативны.

Еще одна вещь - перечисления, как классы. могут иметь поля и методы. Это дает вам возможность включить некоторую дополнительную информацию о каждом типе состояния в само перечисление.

8
ответ дан 29 November 2019 в 23:27
поделиться

Используя int для ссылки на константу, вы не заставляете кого-то действительно использовать эту константу. Так, например, у вас может быть метод, принимающий состояние двигателя, который кто-то может с удовольствием вызвать с помощью:

engine.updateState(1);

Использование enum заставляет пользователя придерживаться поясняющей метки, так что она более понятна.

5
ответ дан 29 November 2019 в 23:27
поделиться

Потому что перечисления обеспечивают безопасность типов. В первом случае вы можете передать любое целое число, и если вы используете enum, вы ограничены Idle и Collecting .

К вашему сведению: http://www.javapractices.com/topic/TopicAction.do?Id=1 .

7
ответ дан 29 November 2019 в 23:27
поделиться

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

Представьте, что позже вы можете добавить новое состояние, например Собрано . Единственный способ сделать это с помощью enum - отредактировать исходный код, что может быть проблемой, если модификация выполняется, когда уже есть много кода, манипулирующего им. Кроме этого, я лично не вижу причин, по которым enum не используется.

Просто моя мысль.

1
ответ дан 29 November 2019 в 23:27
поделиться
  1. Readabiliy - Когда вы используете enums и делаете State.Idle, читатель сразу же понимает, что вы говорите о состоянии простоя. Сравните это с 4 или 5.

  2. Type Safety - Когда вы используете enum, даже по ошибке пользователь не может передать неверное значение, так как компилятор заставит его использовать одно из предварительно объявленных значений в enum. В случае простых целых чисел он может даже передать -3274.

  3. Сохранность - Если бы вы хотели добавить новое состояние Ожидание , то было бы очень просто добавить новое состояние, добавив константу Waiting в состояние перечисления безо всякой путаницы.
1
ответ дан 29 November 2019 в 23:27
поделиться

Причины из спецификации, которую цитирует Лайчик, более подробно объясняются в книге Джоша Блоха «Эффективная Java», пункт 30. Если у вас есть доступ к этой книге, я бы порекомендовал ее прочитать. Java Enums - это полноценные классы, поэтому вы получаете безопасность типов во время компиляции. Вы также можете задать им поведение, улучшив инкапсуляцию.

1
ответ дан 29 November 2019 в 23:27
поделиться

Первое часто встречается в коде, который запускался до версии 1.5. Фактически, другой распространенной идиомой было определение ваших констант в интерфейсе, потому что у них не было кода.

0
ответ дан 29 November 2019 в 23:27
поделиться

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

0
ответ дан 29 November 2019 в 23:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: