Как элегантно использовать enum enum в Java

Java задняя часть
Как элегантно использовать enum enum в Java

Это первый день моего участия в Gengwen Challenge, смотрите подробности мероприятия:Обновить вызов

Согласно главе 6 [Эффективная Java] [Третье издание],Перечисление и аннотацияКак уже упоминалось, тип перечисления относится к типу, состоящему из набора фиксированных констант, формирующих допустимые значения.

Talk is Cheap, Show me the Code!

Типовой шаблон перечисления

Ниже приведен часто используемый шаблон перечисления перечисления.

Код разделен на N части:

  1. все перечисляемые переменные Часть, как показано в коде:

        TO_PAY, TO_DELIVER, TO_RECEIVE, FINISHED;
    
  2. перечисляемые поля экземпляра

    private final int val;
    private final String name;
    

    Перечисления по своей природе неизменяемы, и перечисления могут легко использовать оператор "==". Все поля экземпляра перечисления должны быть установлены в final.

    Также обратите внимание, что: Никогда не получайте значение, связанное с перечислением, на основе его порядкового номера, но храните его в поле экземпляра [Effective Java] [Third Edition], стр. 143.

  3. Методы преобразования других типов в типы перечисления

    /**
     * 	枚举转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(), возвращающему массив всех значений перечисления по порядку.

  4. Абстрактный метод

    Этот способ может помочь нам достичьрежим стратегии.

    С помощью абстрактных методов мы можем избежать использования операторов 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, поэтому не буду его описывать.

Небольшие недостатки в перечислении

При загрузке и инициализации перечислений затраты пространства и времени практически незначительны.