Javaenum-为什么使用 toString 而不是 name

如果在 enum api 中查看方法 name(),它表示:

返回此枚举常数的名称,与其枚举声明中声明的名称完全一致。 大多数程序员应该优先使用 toString 方法, 因为 toString 方法可能返回一个更加用户友好的名称。 这种方法主要是为了在特殊情况下使用而设计的,在这种情况下,正确性取决于获得准确的名称,这种名称不会因版本的不同而有所不同。

为什么使用 toString()更好?我的意思是,当 name ()已经是 final 时,toString 可能会被覆盖。因此,如果您使用 toString 并且有人重写它来返回一个硬编码的值,那么您的整个应用程序将停止运行... ... 同样,如果您查看源代码,toString ()方法将准确地返回名称。这是一回事。

204173 次浏览

如果要进行比较或者在代码中使用某些内部使用的硬编码值,请使用 name()

如果希望向用户显示信息(包括查看日志的开发人员) ,请使用 toString()。永远不要依赖 toString()给出一个特定的值。永远不要针对特定的字符串测试它。如果当有人正确地更改 toString()返回值时,您的代码中断,那么它已经中断了。

来自 javadoc (强调我的) :

返回对象的字符串表示形式 方法返回的字符串 结果应该是一个简洁但信息丰富的表示 这对于 一个可以阅读的人来说很容易。 建议所有 子类覆盖此方法

它实际上取决于您想对返回值做什么:

  • 如果需要获取声明枚举常数所用的确切名称,则应使用 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;
}
}

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

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

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

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

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

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

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

然而,这并不能保证:

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

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

您也可以使用类似下面的代码。我使用 Lombok 来避免为 getter 和构造函数编写一些样板代码。

@AllArgsConstructor
@Getter
public enum RetroDeviceStatus {
DELIVERED(0,"Delivered"),
ACCEPTED(1, "Accepted"),
REJECTED(2, "Rejected"),
REPAIRED(3, "Repaired");


private final Integer value;
private final String stringValue;


@Override
public String toString() {
return this.stringValue;
}
}