Перечисления Java 5 возникли из типового шаблона перечисления из Джошуа Блока Эффективной Java (первое издание), чтобы избежать ошибок перечислений в C / C ++ / C # (которые являются просто тонко завуалированными int-константами) и использование в Java конечных статических int-констант.
В основном int-константы и int-перечисления не безопасны. Вы можете передать любое значение типа int. В C / C ++ вы можете сделать это:
enum A { one, two, three };
enum B { beef, chicken, pork } b = beef;
void func(A a) { ... }
func((A)b);
К сожалению, в типизированном шаблоне enum из Effective Java было много общего, но не все это очевидно. Наиболее примечательным является то, что вам пришлось переопределить private метод readResolve
, чтобы остановить Java, создающий новые экземпляры при десериализации, что нарушило бы простую проверку ссылок (то есть использование оператора ==
вместо equals()
).
Итак, перечисления Java 5 имеют следующие преимущества перед целыми:
- Тип безопасности;
- Перечисления Java 5 могут иметь поведение и реализовывать интерфейсы;
- Перечисления Java 5 имеют несколько очень легких структур данных, таких как
EnumSet
и EnumMap
.
Java 5 перечисляет эти преимущества перед использованием классов:
- Меньше подверженных ошибкам шаблонов (частный конструктор,
readResolve()
и т. Д.);
- Семантическая корректность. Вы видите, что что-то является перечислением, и вы знаете, что оно просто представляет значение. Вы видите класс, и вы не уверены. Может быть, где-то есть метод статической фабрики и т. Д. Перечисления Java 5 гораздо более четко указывают на намерение.