<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />新的“類型安全的枚舉”(typesafe enums)比用整數枚舉(int enum)有什麼優勢?
這個問題在我的書第21項中有詳細的論述。簡要地說:
- 它提供了編譯期類型安全,而整數枚舉根本沒有提供任何類型安全。
- 它們對被枚舉的類型提供了一個適當的命名空間――在整數枚舉中你必須前置一個常數來得到命名空間。
- 它更強大――整數枚舉被編譯進了程序,如果你增加、刪除或者重置了常數的順序你必須重新編譯你的程序。
- 輸出的值是包含各種信息的――如果你打印一個整數枚舉,你只會得到一個數字。
- 它們是對象,你可以把他們放入集合中。
- 它們本質上是類,所以你能增加任意的屬性和方法。
哇,這麼厲害!那麼新的類型安全的枚舉語言特性和你書中類型安全的模式有什麼關係?
這個特性是對類型安全模式的首次語言上的簡單支持。那些有差不多半頁、冗長的、易錯的支持模式的代碼現在看起來很像C/C++中枚舉的聲明:
enum Season { winter, spring, summer, fall }
不過它用起來卻跟C/C++中的枚舉大相徑庭,你可以使用我們剛纔討論的所有的強大的功能。它甚至修正了類型安全模式的主要的缺點:你可以把這個新的語言特性和Switch語句用在一起。
你能給我們舉例說明一下類型安全的枚舉的強大功能嗎?
當然可以。下面的這個枚舉代表了一個美國硬幣:
public enum Coin {
penny(1), nickel(5), dime(10), quarter(25);
Coin(int value) { this.value = value; }
private final int value;
public int value() { return value; }
}
看看,這個常數聲明怎樣調用了一個構造函數,輸入一個整數代表分?還有,這個值怎樣存放在一個帶有公共訪問方法的私有變量裏面?這個就可以勾畫出你能做的事情的輪廓。
您能給我一個類使用您上面定義的enum嗎?
我正準備要說到這個。下面是一個小的例子,它用來輸出分幣表中各個分幣的值和顏色。
public class CoinTest {
public static void main(String[] args) {
for (Coin c : Coin.VALUES)
System.out.println(c + ": /t"
+ c.value() +"¢ /t" + color(c));
}
private enum CoinColor { copper, nickel, silver }
private static CoinColor color(Coin c) {
switch(c) {
case Coin.penny: return CoinColor.copper;
case Coin.nickel: return CoinColor.nickel;
case Coin.dime:
case Coin.quarter: return CoinColor.silver;
default: throw new AssertionError("Unknown coin: " + c);
}
}
}
看看我們如何聲明另外一個關於顏色的枚舉?一個叫做nickeld的硬幣和一個叫做nickel的顏色根本不會引起什麼衝突,因爲硬幣和顏色都有它們自己的命名空間。同時你可以看到我們可以把枚舉常數和Switch語句用在一起。當你希望給一個枚舉類增加一個方法而不想修改你的應用程序的時候,這個性質非常有用。