Перечисления против флагов int?
Просто хотел несколько мнений по этому вопросу. Я всегда использовал флаги типа int, и мне было просто интересно узнать о возможной производительности и простоте использования, если бы я использовал перечисления в Java?
7 ответов
Я очень сомневаюсь, что вы увидите преимущества в производительности, а в некоторых случаях могут даже быть потери производительности, в зависимости от того, как вы их используете. Я сомневаюсь, что они будут значительными, хотя.
Преимущество заключается не в производительности, а в том, что вы выражаете свои намерения более четко, что приводит к более читаемому (и безопасному для типов) коду. Например, с целочисленными флагами ничто не будет жаловаться, если вы попытаетесь использовать (скажем) HTTP_STATUS_UNAUTHORIZED в качестве значения для вашего режима общего доступа к файлам при вызове метода... тогда как, если бы оба из них были перечислениями, параметр был бы строго типизирован как действительно разрешить только режимы обмена файлами (или null, по общему признанию, если вы говорите о Java).
Как обычно, Effective Java говорит это лучше всего:
Программы, использующие
int
Шаблон enum хрупок. Так какint
Перечисления являются константами времени компиляции, они компилируются в клиенты, которые их используют. Еслиint
связанный с константой enum изменен, его клиенты должны быть перекомпилированы. Если это не так, они все равно будут работать, но их поведение будет неопределенным.Нет простого способа перевода
int
константы перечисления в печатаемые строки. Если вы печатаете такую константу или выводите ее из отладчика, все, что вы видите, это число, которое не очень полезно. Не существует надежного способа перебора всехint
константы перечисления в группе, или даже для получения размераint
enum group.
(+ Еще 10 страниц, почему перечисления лучше:-))
Источник: пункт 30: используйте перечисления вместо int
константы
Перечисления более четко выражают то, что вы пытаетесь сделать. Используйте их и не беспокойтесь о производительности; влияние на производительность будет незначительным.
Эквивалентом использования флагов битовой маски является использование EnumSet (что происходит с использованием битовой маски)
enum Colour { RED, GREEN, BLUE }
Set<Colour> colours = EnumSet.noneOf(Colour.class);
colours.add(Colour.RED);
colours.add(Colour.GREEN);
if (colours.contains(Colour.RED)) // true
System.out.println(colours+" contains RED");
if (colours.contains(Colour.BLUE)) // false
В дополнение к типобезопасному коду у вас есть единственная ссылка для совместного использования коллекции (повторное использование)
В основном это одно и то же, за исключением того, что перечисления самодокументированы. Я рекомендую использовать перечисления, как только кто-то другой может связаться с вашим кодом.
Enum тип со своими собственными методами и оптимизированными контейнерами. Вы должны предпочесть это по сравнению с int flags, потому что это безопаснее и, возможно, более эффективно (хотя я сомневаюсь, что в этом очень много всего!).