Java枚举 - 为什么使用toString而不是name

spa*_*uny 166 java enums

如果你在enum api中查看方法,name()它会说:

返回此枚举常量的名称,与其枚举声明中声明的完全相同.大多数程序员应优先使用toString方法,因为toString方法可能会返回一个更加用户友好的名称.此方法主要用于特殊情况,其中正确性取决于获取确切名称,该名称在不同版本之间不会有所不同.

为什么更好用toString()?我的意思是当name()已经是final时,可以覆盖toString.因此,如果您使用toString并且有人覆盖它以返回硬编码值,则整个应用程序都会关闭...另外,如果您查看源代码,则toString()方法将返回完全正确的名称.这是同一件事.

ass*_*ias 191

这实际上取决于你想要对返回值做什么:

  • 如果您需要获得用于声明枚举常量的确切名称,你应该使用name()toString可能已被重写
  • 如果您想以用户友好的方式打印枚举常量,您应该使用toString可能已被覆盖的(或不是!).

当我觉得它可能令人困惑时,我提供了一个更具体的getXXX方法,例如:

public enum Fields {
    LAST_NAME("Last Name"), FIRST_NAME("First Name");

    private final String fieldDescription;

    private Fields(String value) {
        fieldDescription = value;
    }

    public String getFieldDescription() {
        return fieldDescription;
    }
}
Run Code Online (Sandbox Code Playgroud)


Den*_*ret 54

使用name()时要作一比较,或使用硬编码值代码中的一些内部使用.

使用toString()当你想将信息呈现给用户(包括developper看记录).永远不要依赖代码来toString()提供特定的价值.切勿针对特定字符串进行测试.如果您的代码在某人正确更改了toString()返回时中断,那么它已经被破坏了.

来自javadoc(强调我的):

返回对象的字符串表示形式.通常,toString方法返回一个"文本表示"此对象的字符串.结果应该是一个简洁但信息丰富的表示,便于人们阅读.建议所有子类都重写此方法.


Ale*_*exR 23

name()是一种"内置"的方法enum.这是最终的,你不能改变它的实现.它在写入时返回枚举常量的名称,例如大写,没有空格等.

比较MOBILE_PHONE_NUMBERMobile phone number.哪个版本更具可读性?我相信第二个.这是区别:name()总是返回MOBILE_PHONE_NUMBER,toString()可以覆盖返回Mobile phone number.

  • 这不对!toString()仅在您覆盖它以返回此值时返回"移动电话号码".否则它将返回`MOBILE_PHONE_NUMBER` (16认同)
  • @AlexR您可能需要在答案中加入您的上述评论,以使其100%正确 (12认同)
  • 我同意@artfullyContrived,因为在我阅读你的评论之前,这对我来说并不明显. (4认同)
  • @spayny,很明显你必须覆盖`toString()`.问题是`name()`不能被覆盖,因为它是最终的. (2认同)

cod*_*ing 13

虽然大多数人盲目地遵循javadoc的建议,但是在非常具体的情况下你想要实际避免使用toString().例如,我在我的Java代码中使用枚举,但它们需要序列化到数据库,然后再返回.如果我使用toString()那么我在技术上会受到其他人指出的被覆盖的行为的影响.

另外,也可以从数据库中反序列化,例如,这应该总是在Java中工作:

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

虽然这不能保证:

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

顺便说一句,我发现Javadoc明确地说"大多数程序员应该"是非常奇怪的.我在枚举的toString中发现很少的用例,如果人们使用它作为"友好名称",这显然是一个糟糕的用例,因为他们应该使用与i18n更兼容的东西,在大多数情况下,使用name()方法.

  • 谢谢回答.我提出这个问题差不多5年了,我还没有使用toString()方法作为枚举!99%的时间我使用枚举完全符合您的描述:对数据库中的枚举名称进行序列化和反序列化. (2认同)

小智 5

name() 实际上是枚举的 Java 代码中的文本名称。这意味着它仅限于可以实际出现在您的 java 代码中的字符串,但并非所有想要的字符串都可以在代码中表达。例如,您可能需要一个以数字开头的字符串。name() 永远无法为您获取该字符串。


Mar*_*cin 5

当name()和toString()有意义时的一个实际示例是一种模式,其中使用单值枚举定义单例。起初看起来很令人惊讶,但是很有意义:

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

    /* ...behavior... */

    @Override
    String toString() {
      return "SingletonComponent"; // better than default "INSTANCE"
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下:

SingletonComponent myComponent = SingletonComponent.INSTANCE;
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better
Run Code Online (Sandbox Code Playgroud)