关于Java枚举:Java枚举 – 为什么使用toString而不是name

Java enum - why use toString instead of name

如果在枚举API中查看方法name(),它会说:

Returns the name of this enum constant, exactly as declared in its enum declaration.
Most programmers should use the toString method in preference to this one,
as the toString method may return a more user-friendly name.
This method is designed primarily for use in specialized situations where correctness depends on getting the exact name, which will not vary from release to release.

为什么使用toString()更好?我的意思是,当name()已经是final时,toString可能会被重写。所以,如果您使用ToString,并且有人重写它以返回硬编码值,那么您的整个应用程序都将关闭…另外,如果您在源代码中查找,toString()方法将返回准确的名称。是一样的。


它实际上取决于您希望如何处理返回值:

  • 如果需要获得用于声明枚举常量的确切名称,则应使用name(),因为toString可能已被重写。
  • 如果要以用户友好的方式打印枚举常量,则应使用可能已被重写(或未重写)的toString。.
  • 小精灵

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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;
        }
    }


    当您想要进行比较时,可以使用name(),或者在代码中使用硬编码值进行一些内部使用。

    当您想向用户提供信息(包括查看日志的开发人员)时,可以使用toString()。不要依赖于代码中的toString()给出特定的值。不要用特定的字符串测试它。如果您的代码在有人正确更改toString()返回时中断,那么它已经中断了。

    来自JavaDoc(Emphasis Mine):

    Returns a string representation of the object. In general, the
    toString method returns a string that"textually represents" this
    object. The result should be a concise but informative representation
    that is easy for a person to read. It is recommended that all
    subclasses override this method.


    name()enum的"内置"方法。它是最终的,您不能更改它的实现。它在写入时返回枚举常量的名称,例如大写,不带空格等。

    比较MOBILE_PHONE_NUMBERMobile phone number。哪个版本更可读?我相信第二个。这就是区别:name()总是返回MOBILE_PHONE_NUMBERtoString()可能被重写以返回Mobile phone number


    虽然大多数人盲目地遵循JavaDoc的建议,但在某些特定的情况下,您实际上希望避免ToString()。例如,我在Java代码中使用枚举,但是它们需要序列化到数据库,然后再返回。如果我使用toString(),那么从技术上讲,我将受到其他人指出的被重写行为的影响。

    此外,还可以从数据库中取消序列化,例如,这应该始终在Java中工作:

    江户十一〔16〕号

    鉴于此,不保证:

    埃多克斯1〔17〕

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    enum SingletonComponent {
        INSTANCE(/*..configuration...*/);

        /* ...behavior... */

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

    在这种情况下:

    1
    2
    3
    SingletonComponent myComponent = SingletonComponent.INSTANCE;
    assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
    assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better


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