用enum代替int常量

枚舉類型是指由一組固定的常量組成合法值的類型。例如一年中的季節,太陽系中的行星或者一副牌中的花色。在編程語言中還沒有引入枚舉類型之前,表示枚舉類型的常用模式是聲明一組具名的int常量,每個類型成員一個常量:

public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOD = 2;

這種方法稱作int 枚舉模式,存在着諸多不足。它在類型安全性和使用方便性方面沒有任何幫助。如果你將apple傳到想要orange的方法中,編譯器也不會出現警告,還會用==操作符將apple與orange進行對比,甚至更糟糕。


JAVA枚舉背後的基本想法非常簡單:它們是通過公有的靜態final域爲枚舉常量導出實例的類。因爲沒有可以訪問的構造器,枚舉類型是真正的final。因爲客戶端既不能創建枚舉常量導出的類。因爲沒有可以訪問的構造器,枚舉類型是真正的final 。因爲客戶端既不能創建枚舉類型的實例,也不能對它進行擴展,因此很可能 沒有實例,而只有聲明過的枚舉常量。換句話說,枚舉類型是實例受控的。它們是單例的泛型化,本質上是單元素的枚舉。

public enum PayrollDay {
	MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(
			PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(
			PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
	private final PayType payType;

	PayrollDay(PayType payType) {
		this.payType = payType;
	}
	
	double pay(double hoursWorked, double payRate) {
		return payType.pay(hoursWorked, payRate);
	}

	private enum PayType {
		WEEKDAY {
			double overtimePay(double hours, double payRate) {
				return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT)
						* payRate / 2;
			}
		},
		WEEKEND {
			double overtimePay(double hours, double payRate) {
				return hours * payRate / 2;
			}
		};
		private static final int HOURS_PER_SHIFT = 8;

		abstract double overtimePay(double hours, double payRate);

		double pay(double hoursWorked, double payRate) {
			double basePay = hoursWorked * payRate;
			return basePay + overtimePay(hoursWorked, payRate);
		}
	}
}

總之:與int常量相比,枚舉的類型優勢是不言而喻的。枚舉要易讀得多,也更加安全,功能更加強大。許多枚舉都不需要顯式的構造器或者成員,但許多其它枚舉則受益於“每個常量與屬性的關聯”以及“提供行爲受這個屬性影響的方法”。只有極少數的枚舉受益於將多種行爲與單個方法關聯。在這種相對少見的情況下,特定於常量的方法要優先於啓用自有值的枚舉。如果多個枚舉常量同時享有相同的行爲,則考慮策略枚舉。

摘自:effective java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章