Практическое применение Enum

1,00
р.
Меня всегда волновал вопрос класса Enum: какие у них есть преимущества перед обычными static final примитивами?
И, если можно, поделитесь вашим опытом, в котором использование Enum было бы действительно оправданным.

Ответ
enum имеет ряд преимуществ при использовании в сравнении с static final int. И использовать его стоит в том случае если вам нужны эти преимущества.
Главным отличием является то что используя enum вы можете проверить тип данных.
Например:
public class SomeClass { public static int RED = 1 public static int BLUE = 2 public static int YELLOW = 3 public static int GREEN = 3 // Совпадающие значения
private int color
public void setColor(int color) { this.color = color } }
При этом вы можете передать в класс любое значение int.
new SomeClass().setColor(999)
Следовательно, основные проблемы использования static final int это:
Необходимость проверки вводимых данных. Нет никакой защиты от создания static final int переменной с дублирующимся значением.
Еще одним преимуществом enum является возможность перегружать методы.
public enum UnitConverter{ METERS{ @Override public double toMiles(final double meters){ return meters * 0.00062137D }
@Override public double toMeters(final double meters){ return meters } }, MILES{ @Override public double toMiles(final double miles){ return miles }
@Override public double toMeters(final double miles){ return miles / 0.00062137D } }
public abstract double toMiles(double unit) public abstract double toMeters(double unit) }
Недостатки использования enum
К ним не применимы операторы >, <, >=, <=. Следовательно enum не стоит применять в списке последовательных данных. enum также требует больше памяти для хранения чем обычная константа. <br>IntDef и StringDef в Android
Google не рекомендует использовать enum в Android приложениях из-за того что это требует больше памяти. Вместо этого для Android можно использовать IntDef и StringDef которые позволяют ограничивать пространство значений для обычных констант. Следовательно, вы получаете главное преимущество enum не теряя в использовании памяти. Это практика повсеместно используется в стандартных классах Android:
/** @hide */ @IntDef({VISIBLE, INVISIBLE, GONE}) @Retention(RetentionPolicy.SOURCE) public @interface Visibility {}
/** * This view is visible. * Use with {@link #setVisibility} and {@code * android:visibility}. */ public static final int VISIBLE = 0x00000000
/** * This view is invisible, but it still takes up space for layout purposes. * Use with {@link #setVisibility} and
{@code * android:visibility}. */ public static final int INVISIBLE = 0x00000004
/** * This view is invisible, and it doesn't take any space for layout * purposes. Use with {@link #setVisibility} and
{@code * android:visibility}. */ public static final int GONE = 0x00000008
В принимающем методе используется специальная аннотация:
public void setVisibility(@Visibility int visibility) { setFlags(visibility, VISIBILITY_MASK) if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false) }
В таком случае вы не сможете использовать другую константу для этого метода:
view.setVisibility(456) //Error: Must be one of: View.VISIBLE, View.INVISIBLE, View.GONE