2011-08-22 16 views
34

當你定義的東西,可以在你的界面是「不確定」的枚舉,你應該是否應該爲Java枚舉定義一個空值/未知值?

  • 定義爲一個獨立的枚舉值,或
  • 只使用enumValue = NULL對於這種情況?

例如,

serviceX.setPrice(價格priceEnum)

enum Price { 
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN 
} 

並在需要時

priceEnum.UNKNOWN

enum Price { 
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE 
} 

和priceEnum = null當需要?

對此有一點辯論。有一點可以想到:

  • 使用Price.UNKNOWN保存了一些「if(price == null)」代碼。您可以處理價格X的所有值在單一的switch-case
  • 根據視圖技術,它可能更容易使用Price.UNKNOWN樣的原因代碼「幻數」的問題進行本地化Price.UNKNOWN
  • ,IMO 。這裏我們有Price.UNKNOWN,其他地方可能是Color.UNDEFINED,Height.NULLVALUE等
  • 使用priceValue = null與Java中處理其他數據類型的方式更加一致。對於未知值,我們有Integer i = null,DomainObject x = null,String s = null,是嗎?
  • Price.UNKNOWN強制您決定是否允許所有用例均爲空值。我們可能有方法Price getPrice(),它可能會返回Price.UNKNOWN和setPrice(Price p),它不允許接受Price.UNKNOWN。由於Price.UNKNOWN始終包含在枚舉的值中,因此這些接口看起來有點不潔。我知道priceValue = NULL,則同樣的問題(你不能在接口定義空是否被接受與否),但感覺有點清潔,少一點誤解(?)
+7

你不能在交換機中使用'null',這是一個主要的缺點。 – bestsss

+0

所有的好點。減少空值處理的負擔,並且更具體地說明「空值」意味着什麼是Price.UNKNOWN。另外,關於「空對象模式」的好處,它使得Price.UNKNOWN感覺更像「有效」並且被普遍接受的解決方案。但是,沒有人對Price.UNKNOWN消極方面有同感嗎?我覺得Price.UNKNOWN污染了枚舉的值集。在showAllPrices()中說,我不能枚舉所有的枚舉值,我不得不添加如果(!Price.UNKNOWN),這感覺有點骯髒和「魔法 - 數字」。 – user449236

+0

* @ user449236 *:如果您不想檢查此特殊值,請爲每個枚舉添加一個「顯示」標誌並檢查它。更清潔,更靈活。 –

回答

12

我說去Price.UNKNOWN如果這是價格的有效價值。

我同意你提到的處理空引用的缺點,我認爲他們足以激發這個決定。例如(以及一些較老的Haskell),新的語言一起消除空引用,並且使用選項/可能是monad,而不是...出於充分的原因。

27

這實際上是應用Null Object pattern的一個示例。恕我直言,總是有一個虛擬對象而不是null更好。例如,您可以將虛擬方法添加到空對象,而不是使用空值檢查來散佈您的代碼。很方便。

另外,enum的名義給你一些額外的語義:是價格未知不確定,不守信,還不知道?如果價格是null,這意味着什麼?

更新:由於Aaron Digulla指出,空對象模式需要內存。但大多數情況下並非如此。在傳統的實現中,你通常有一個用於Null對象的單例,因爲不需要單獨的實例。它使用枚舉變得更好,因爲你可以免費獲得單例語義。

另一點是null引用和引用某些對象佔用相同的內存量(比如在32位機器上說4個字節)。它是被引用的對象,佔用一些額外的內存。但如果這是一個單身人士,這裏幾乎沒有記憶開銷。

+0

+1提到的模式。需要注意的一點:人們不使用模式的主要原因是因爲它需要內存('null'指針不需要內存)。但是他們忘記了這會使代碼更加複雜( - 花費更多的時間來開發和調試它),複雜性與錯誤的數量密切相關,更多的代碼行意味着*代碼*需要更多的內存,因此決策往往是*全部*前沿損失。 –

+0

好點,我實際編輯了我的問題來解決你的評論。 –

+0

'人們不使用模式的主要原因是因爲它需要內存(空指針不需要內存)'主要原因是性能,因爲空檢查很容易被JIT消除,空檢查是硬件輔助的等等。 – bestsss

1

這取決於你打算如何使用這個枚舉。如果您在switch/case語句中使用它,則無關緊要。 如果您在枚舉中創建方法,您實際上必須定義UNKNOWN。

例如,你可以定義抽象方法 public abstract Icon icon();

到您的枚舉,然後實施價格中的每個成員此方法。可能你會想要顯示未知價格的問號。在這種情況下,只需實施創建適當圖標的方法icon()

1

Enum-Switch-Null-Trap。 因此,它似乎就像任何屬性是一個對象, 如果它不存在,那麼它是null

0

顏色或高度將在程序邏輯中使用。他們無法處理未定義的顏色。 價格是userdata,可能未知。 顏色可能是其他用戶數據,但要在代碼中用作顏色,必須定義它們。

所以價格可能是UNKNOWN(而不是空),顏色不是(null可能表示錯誤)。