2012-11-08 62 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

相关问题