Это первый день моего участия в Gengwen Challenge, смотрите подробности мероприятия:Обновить вызов
Согласно главе 6 [Эффективная Java] [Третье издание],Перечисление и аннотацияКак уже упоминалось, тип перечисления относится к типу, состоящему из набора фиксированных констант, формирующих допустимые значения.
Talk is Cheap, Show me the Code!
Типовой шаблон перечисления
Ниже приведен часто используемый шаблон перечисления перечисления.
Код разделен на N части:
-
все перечисляемые переменные Часть, как показано в коде:
TO_PAY, TO_DELIVER, TO_RECEIVE, FINISHED;
-
перечисляемые поля экземпляра
private final int val; private final String name;
Перечисления по своей природе неизменяемы, и перечисления могут легко использовать оператор "==". Все поля экземпляра перечисления должны быть установлены в final.
Также обратите внимание, что: Никогда не получайте значение, связанное с перечислением, на основе его порядкового номера, но храните его в поле экземпляра [Effective Java] [Third Edition], стр. 143.
-
Методы преобразования других типов в типы перечисления
/** * 枚举转int * @return */ public int getVal() { return val; } /** * int转枚举 * @param val * @return */ public static OrderState getOrderState(int val) { for (OrderState orderState : OrderState.values()) { if (orderState.val == val) { return orderState; } } throw new RuntimeException("错误的订单状态"); }
Особое внимание уделено: методу values(), возвращающему массив всех значений перечисления по порядку.
-
Абстрактный метод
Этот способ может помочь нам достичьрежим стратегии.
С помощью абстрактных методов мы можем избежать использования операторов switch-case, чтобы не забыть добавить связанные специальные операции к соответствующим значениям при добавлении значений перечисления в будущем. Вы также можете использовать switch-case в перечислениях.
В [Эффективная Java]:«Операция switch-case в перечислении подходит для добавления поведения, зависящего от константы, к внешнему типу перечисления».
Кроме того, согласно пункту 38 [Effective Java] [Third Edition] мы можем эмулировать расширяемые перечисления с интерфейсами.
/**
* 订单状态
*/
public enum OrderState {
TO_PAY("待付款", 0) {
@Override
public boolean deliver() {
return false;
}
},
TO_DELIVER("待发货", 1) {
@Override
public boolean deliver() {
return true;
}
},
TO_RECEIVE("待收货", 2) {
@Override
public boolean deliver() {
return false;
}
},
FINISHED("已完成", 3) {
@Override
public boolean deliver() {
return false;
}
};
/**
* 枚举天生不可变,所有的域都应声明为final
*/
private final int val;
private final String name;
/**
* 私有修饰,防止外部调用
* @param name
* @param val
*/
private OrderState(String name, int val) {
this.name = name;
this.val = val;
}
/**
* 枚举转int
* @return
*/
public int getVal() {
return val;
}
public String getName() {
return name;
}
/**
* int转枚举
* @param val
* @return
*/
public static OrderState getOrderState(int val) {
for (OrderState orderState : OrderState.values()) {
if (orderState.val == val) {
return orderState;
}
}
throw new RuntimeException("错误的订单状态");
}
/**
* 抽象方法:发货
* @return
*/
public abstract boolean deliver();
}
Когда следует использовать перечисления
Перечисление следует использовать всякий раз, когда требуется фиксированный набор констант, а его члены известны во время компиляции. Однако набор констант в типе перечисления не обязательно должен быть постоянным все время.
Кроме того, я не очень часто использую EnumMap, поэтому не буду его описывать.
Небольшие недостатки в перечислении
При загрузке и инициализации перечислений затраты пространства и времени практически незначительны.