[英]Java enum - why use toString instead of name
如果您查看方法name()
处的枚举 api,它会说:
返回此枚举常量的名称,与在其枚举声明中声明的完全相同。 大多数程序员应该优先使用 toString 方法而不是这个方法,因为 toString 方法可能会返回一个更用户友好的名称。 此方法主要设计用于特殊情况,其中正确性取决于获取确切名称,不会因版本而异。
为什么最好使用toString()
? 我的意思是当 name() 已经是 final 时 toString 可能会被覆盖。 因此,如果您使用 toString 并且有人覆盖它以返回一个硬编码值,那么您的整个应用程序就会关闭……此外,如果您查看源代码,toString() 方法将准确返回名称,并且仅返回名称。 这是同一件事。
这实际上取决于您想对返回值做什么:
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()
。
当您想向用户(包括查看日志的开发人员)显示信息时,请使用toString()
)。 永远不要依赖toString()
给出特定值的代码。 切勿针对特定字符串对其进行测试。 如果您的代码在有人正确更改toString()
返回值时中断,则它已经中断。
从javadoc(强调我的):
返回对象的字符串表示形式。 通常, toString 方法返回一个“文本表示”此对象的字符串。 结果应该是一个简洁但内容丰富的表示,易于人们阅读。 建议所有子类都覆盖此方法。
name()
是enum
的“内置”方法。 它是最终的,你不能改变它的实现。 它返回写入时枚举常量的名称,例如大写,不带空格等。
比较MOBILE_PHONE_NUMBER
和Mobile phone number
。 哪个版本更易读? 我相信第二个。 这是区别: name()
总是返回MOBILE_PHONE_NUMBER
, toString()
可能会被覆盖以返回Mobile phone number
。
虽然大多数人盲目地遵循 javadoc 的建议,但在某些非常具体的情况下,您确实希望避免使用 toString()。 例如,我在 Java 代码中使用枚举,但它们需要序列化到数据库,然后再返回。 如果我使用 toString() 那么我在技术上会像其他人指出的那样受到覆盖的行为的影响。
此外,还可以从数据库中反序列化,例如,这应该始终适用于 Java:
MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());
而这不能保证:
MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());
顺便说一句,我发现 Javadoc 明确地说“大多数程序员应该”很奇怪。 我在枚举的 toString 中发现很少的用例,如果人们将它用于“友好名称”,这显然是一个糟糕的用例,因为他们应该使用与 i18n 更兼容的东西,在大多数情况下,使用 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
name() 实际上是枚举的 Java 代码中的文本名称。 这意味着它仅限于可以实际出现在您的 java 代码中的字符串,但并非所有想要的字符串都可以在代码中表达。 例如,您可能需要一个以数字开头的字符串。 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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.