Java枚举-为什么使用toString而不是name
如果查看enum api中的方法,它会说: 返回此枚举常量的名称,与在其枚举声明中声明的名称完全相同。 大多数程序员应该优先使用toString方法, 因为toString方法可能会返回一个更为用户友好的名称。 此方法主要设计用于特定情况,其中正确性取决于获得确切的名称,不同版本的名称不会有所不同 为什么使用Java枚举-为什么使用toString而不是name,java,enums,Java,Enums,如果查看enum api中的方法,它会说: 返回此枚举常量的名称,与在其枚举声明中声明的名称完全相同。 大多数程序员应该优先使用toString方法, 因为toString方法可能会返回一个更为用户友好的名称。 此方法主要设计用于特定情况,其中正确性取决于获得确切的名称,不同版本的名称不会有所不同 为什么使用toString()更好?我的意思是,当name()已经是final时,toString可能会被重写。因此,如果您使用toString,而有人覆盖它以返回硬编码值,则整个应用程序都将关闭。。
toString()
更好?我的意思是,当name()已经是final时,toString可能会被重写。因此,如果您使用toString,而有人覆盖它以返回硬编码值,则整个应用程序都将关闭。。。此外,如果您查看源代码,toString()方法将准确且仅返回名称。这是一样的。当您想要进行比较或在代码内部使用硬编码值时,请使用name()
当您想向用户(包括查看日志的开发人员)提供信息时,请使用toString()
。千万不要在代码中依赖于toString()
给定特定值。永远不要针对特定字符串进行测试。如果您的代码在有人正确更改toString()
返回时中断,那么它已经中断
从javadoc(我的重点):
返回对象的字符串表示形式。总的来说
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()
是enum
的“内置”方法。它是最终的,您不能更改它的实现。它在写入时返回枚举常量的名称,例如大写,不带空格等
比较
手机号码
和手机号码
。哪个版本更可读?我相信第二个。这就是区别:name()
总是返回MOBILE\u PHONE\u NUMBER
,toString()
可能会被覆盖以返回MOBILE PHONE NUMBERname()实际上是枚举的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;
}
}
这是不对的!!toString()仅当覆盖它以返回该值时才返回移动电话号码。否则它将返回MOBILE\u PHONE\u NUMBER
@spayny,显然您必须重写toString()
。问题是,name()
不能被覆盖,因为它是最终的。@AlexR您可能需要在答案中加入您的上述注释,使其100%正确。我同意@artfullyContrived,因为在我阅读您的注释之前,它对我来说并不明显。是的,您是对的。。。一个很好的例子是Guava的枚举谓词。您可以在枚举中重写toString()
,但其他人无法扩展和重写它。您无法扩展枚举。谢谢您的回答。我问这个问题已经快5年了,我还没有对枚举使用toString()方法!99%的情况下,我使用枚举的目的与您描述的完全相同:将枚举名称序列化和反序列化到数据库中或从数据库中序列化。如果您通过Web服务与现有系统(如大型机)集成,或只是为现有数据库创建一个新的前端,则经常会使用带有连字符的枚举值。这是可以接受的。虽然如果他们让enum有一个基类,事情会更容易。