2012-11-08 61 views
137

如果您在方法枚舉API看name()它說:的Java枚舉 - 爲什麼使用的toString,而不是名稱

返回此枚舉常量的名稱,正是因爲在枚舉聲明中宣佈。 由於toString方法可能會返回一個更加用戶友好的名稱,因此大多數程序員應該優先使用toString方法,該方法優先於 。 此方法主要用於特殊情況,其中正確性取決於獲取確切的名稱,而不會因發佈版本而異。

爲什麼最好用toString()?我的意思是,當name()已經是final時,toString可能被覆蓋。所以,如果你使用toString,並且有人重寫它以返回一個硬編碼的值,那麼你的整個應用程序就關閉了。另外,如果你查看源代碼,toString()方法會返回完全正確的名稱。這是同一件事。

+3

你可以在你的枚舉中重寫'toString()',但沒有其他人可以擴展和覆蓋它。你不能擴展枚舉。 –

回答

157

這真的取決於你想要返回值做什麼:

  • 如果您需要獲得用於聲明枚舉常量的確切名稱,你應該使用name()toString可能有被覆蓋
  • 如果你想以一種用戶友好的方式打印枚舉常量,你應該使用toString可能被覆蓋(或不!)。

當我覺得它可能會造成混亂,我提供了一個更具體的getXXX方法,例如:

41

使用name()要進行比較或在代碼中使用硬編碼值作爲內部使用。

使用toString()當你想向用戶展示信息(包括查看日誌的開發人員)。永遠不要依靠toString()上的代碼給出具體的價值。切勿對特定的字符串進行測試。如果您的代碼在有人正確更改toString()退貨時中斷,那麼它已經被破壞。

根據JavaDoc(重點煤礦):

返回該對象的字符串表示。通常,toString方法返回一個字符串,該字符串表示「文本表示」此 對象。結果應該是一個簡明但內容豐富的表示 ,一個人很容易讀建議所有 子類重寫此方法。

18

name()enum一個「內置」的方法。它是最終的,你不能改變它的實現。它在寫入時返回枚舉常量的名稱,例如大寫,無空格等。

比較MOBILE_PHONE_NUMBERMobile phone number。哪個版本更具可讀性?我相信第二個。這是區別:name()總是返回MOBILE_PHONE_NUMBER,toString()可能會被覆蓋以返回Mobile phone number

+15

這是不正確的! toString()只有在覆蓋它才返回這個值時纔會返回「手機號碼」。否則它將返回'MOBILE_PHONE_NUMBER' – spauny

+1

@spayny,顯然你必須重寫'toString()'。值得注意的是'name()'不能被覆蓋,因爲它是最終的。 – AlexR

+12

@AlexR您可能需要在答案中加入您的上述評論才能使其100%正確 – artfullyContrived

4

name()實際上是enum的java代碼中的文本名稱。這意味着它僅限於實際出現在您的java代碼中的字符串,但並非所有期望的字符串都可以用代碼表示。例如,您可能需要一個以數字開頭的字符串。 name()將永遠無法爲您獲取該字符串。

3

name()和toString()有意義不同的一個實際示例是使用單值枚舉定義單例的模式。它看起來令人驚訝的在第一,但讓有很大的意義:

enum SingletonComponent { 
    INSTANCE(/*..configuration...*/); 

    /* ...behavior... */ 

    @Override 
    String toString() { 
     return "SingletonComponent"; // better than default "INSTANCE" 
    } 
} 

在這種情況下:

SingletonComponent myComponent = SingletonComponent.INSTANCE; 
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah 
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better 
+0

是的,你是對的...一個很好的例子是番石榴的枚舉Predicates – spauny

11

雖然大多數人盲目跟風的Javadoc的建議,也有要非常具體情況實際上避免了toString()。例如,我在我的Java代碼中使用枚舉,但它們需要序列化到數據庫,然後再返回。如果我使用toString(),那麼我在技術上會受其他人指出的重寫行爲的影響。

另外一個也可以反序列化從數據庫中,例如,這應該總是在Java中的工作:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());

雖然不能保證這一點:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());

通過就我而言,我覺得Javadoc明確地說「大多數程序員應該」是很奇怪的。我發現在枚舉的toString中使用很少的用例,如果人們將它用於「友好名稱」,這顯然是一個糟糕的用例,因爲他們應該使用與i18n更兼容的東西,在大多數情況下,使用name()方法。

+2

感謝您的回答。距離我問這個問題已經差不多5年了,我還沒有使用toString()方法來枚舉枚舉! 99%的時間我使用枚舉完全是你所描述的:序列化和從數據庫中將枚舉名解序列化。 – spauny

相關問題