2010-02-09 106 views
20

我正在看一些由公司其他部分維護的Java代碼,順便說一下一些前C和C++開發人員。有一兩件事,是無處不在的是使用靜態整型常量,比如Java枚舉與靜態常量

class Engine { 
    private static int ENGINE_IDLE = 0; 
    private static int ENGINE_COLLECTING = 1; 
    ... 
} 

除了缺少的「最終」預選賽,我有點被這種代碼困擾。我本來希望看到的,主要是來自學校的Java培訓,會更像

class Engine { 
    private enum State { Idle, Collecting }; 
    ... 
} 

但是,這些論據讓我失望。如果有的話,爲什麼後者比前者好?

+4

用於使常數爲'final'的+1。 – uckelman 2010-02-09 13:49:29

回答

24

爲什麼如果說畢竟是後者比前者更好 ?

它更好,因爲它給你類型安全和自我記錄。使用整型常量,您必須查看API文檔以找出哪些值是有效的,並且沒有任何東西阻止您使用無效值(或者更糟糕的是,完全不相關的整數常量)。使用枚舉,方法簽名直接告訴你什麼值是有效的(IDE自動完成將起作用),並且不可能使用無效值。

的「整型常量枚舉」模式是不幸的是很常見的,即使是在Java標準API(並從那裏廣泛效仿),因爲Java沒有枚舉前的Java 5

+3

+1,因爲你是唯一一個提到自我文檔的人,如果你有一個方法,接受(或返回)一個代表一些代碼的int,那麼沒有doc或者source就沒有機會得出int的語義。但枚舉有一個名稱爲每個值和簽名是直接(通過類型)連接到枚舉。 – Mnementh 2010-02-09 13:33:52

+1

+1「self-documenting」和「IDE autocompletion will work」 – 2010-02-09 14:12:14

0

前者在1.5以前開始的代碼中很常見。實際上,另一個常見的習慣用法是在界面中定義常量,因爲它們沒有任何代碼。

+0

但是這種做法也鼓勵使用繼承這些常量,這有點難看。 :( – 2010-02-09 13:28:36

+0

@大衛:這是最少的問題,「整型常量枚舉」原因 – 2010-02-09 13:29:51

+0

@邁克爾:但問題沒有少 – 2010-02-09 13:31:26

5

通過使用int來引用一個常量,你不會強迫某人實際使用該常量。因此,舉例來說,你可能有這需要發動機狀態的方法,對此有人會樂意與調用:

engine.updateState(1); 

使用的enum用戶堅持使用說明標籤,所以它更清晰可辨。

1

有當靜態的情況constance是首選的(而不是代碼是具有大量依賴性的遺留代碼),那就是當該值的成員不是/可能以後不是有限的。

想象一下,如果您以後可能會添加新的狀態,如Collected。使用枚舉的唯一方法是編輯原始代碼,如果在已經有很多代碼操作的情況下完成修改,則代碼可能會出現問題。除此之外,我個人認爲沒有理由不使用枚舉。

只是我的想法。

+0

但是,添加新狀態可能需要代碼中的其他更改(意味着處理新狀態)。所以情況不太可能。遺留代碼可能是此方法適用的唯一地方。 – Lajcik 2010-02-09 13:38:45

1
  1. Readabiliy - 當您使用枚舉和做State.Idle,讀者立即知道你正在談論一個閒置狀態。將此與4或5進行比較。

  2. 類型安全 - 當使用枚舉,甚至誤,用戶無法通過一個錯誤的值,因爲編譯器將迫使他使用在枚舉預申報值之一。如果是簡單整數,他甚至可以通過-3274。

  3. 可維護性 - 如果你想添加一個新的狀態Waiting,那麼這將是很容易通過增加您的枚舉狀態恆定的等待沒有任何casuing混亂添加新的狀態。
8

從官方文檔的摘錄,http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

這個模式有很多問題,比如:

  • 沒有類型安全 - 因爲一個賽季只是一個int你可以通過在任何其他需要季節的int值,或者添加兩個季節(這沒有意義)。
  • 沒有命名空間 - 你必須前綴一個int枚舉的常量用於字符串(在這種情況下SEASON_),以避免與其他INT枚舉類型的碰撞。
  • 脆性 - 因爲int枚舉是編譯時常量,所以它們被編譯到使用它們的客戶機中。如果在兩個現有常量之間添加新的常量或更改了順序,則必須重新編譯客戶端。如果他們不是,他們仍然會跑,但他們的行爲將是不確定的。
  • 打印的值是無信息的 - 因爲他們只是整數,如果打印一出所有你得到的是一個數字,它不能告訴你它代表什麼,甚至它是什麼類型。

而這只是涵蓋它。一個單詞的論點是,枚舉更具可讀性和信息性。

還有一件事是枚舉,就像類一樣。可以有字段和方法。這使您可以選擇包含有關枚舉本身中每種類型狀態的其他信息。

0

枚舉還給你很大的靈活性。由於枚舉本質上是類,所以可以用有用的方法來擴充它們(例如提供與枚舉中的某個值相對應的國際化資源字符串,在枚舉類型的實例和可能需要的其他表示之間來回轉換等等。 )

1

從規範,這Lajcik報價的原因,進行了更詳細的喬希布洛赫的有效的Java解釋說,第30項。如果你有機會獲得這本書,我建議你仔細閱讀它。 Java Enums是完整的類,這就是爲什麼你需要編譯時類型安全。你也可以給他們行爲,給你更好的封裝。