为什么要使用枚举而不是常量?从软件设计和可读性方面来看,哪种更好?

103

我有一个场景,其中有 玩家类型 ARCHER,WARRIOR, 和 SORCERER
在Player类中应该使用什么来表示一个玩家类型?
是使用常量 final static String 变量 还是 一个枚举?为什么?
请给出原因。


1
我不会使用字符串变量。如果需要,可以使用一个int变量(并为各种类型命名常量)。 - Thilo
6
这个答案对你有用吗?https://dev59.com/0nRB5IYBdhLWcg3weHHx?rq=1 - Jimmy
可能是什么是Enum有用的?的重复。 - oers
1
可能是枚举和常量。何时使用?的重复问题。 - RBz
2
@RBz 这并不改变Java中的枚举与C#和其他类C语言中的枚举非常不同的事实。即使它被标记为语言无关,该问题的答案仍然都是针对C#的。 - Mark Rotteveel
显示剩余2条评论
5个回答

157
假设您使用常量字符串(或int值-对它们也是一样的):
// Constants for player types
public static final String ARCHER = "Archer";
public static final String WARRIOR = "Warrior";

// Constants for genders
public static final String MALE = "Male";
public static final String FEMALE = "Female";

如果你不知道数据的类型,就可能导致代码出现错误:

String playerType = Constants.MALE;

如果您使用枚举,那么代码将如下所示:

// Compile-time error - incompatible types!
PlayerType playerType = Gender.MALE;

同样地,枚举(enums)给出一个有限的值集合:
String playerType = "Fred"; // Hang on, that's not one we know about...

vs

PlayerType playerType = "Fred"; // Nope, that doesn't work. Bang!

此外,Java中的枚举类型可以有更多与其相关联的信息,并且还可以具有行为。这样更加全面。

4
枚举和常量之间的性能比较怎么样? - Waqas
3
@waqas716:枚举是引用类型,但每个值只有一个对象,因此您不太可能浪费太多内存。如果您想要其他性能差异,您需要说明您感兴趣的内容。 - Jon Skeet
1
我必须将此Player对象发送到Web服务,因此我将把此对象转换为Json字符串,在这种情况下,我应该使用字符串常量还是枚举? - Waqas
你总是可以使用映射(Map)从枚举类型(Enums)到字符串(Strings)之间进行转换。如果需要的话,还有一个双向映射(Bi-Directional Map)在Apache的Commons Collections 4中,可以让你从字符串到枚举类型之间进行转换:https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/BidiMap.html。 - Jacob Holloway

19

枚举类型限制您使用所需的输入集,而即使您使用常量字符串,仍然可以使用其他不属于逻辑的字符串。

这有助于您在输入数据时不犯领域外的错误,并提高程序的可读性。

此外,如果需要,您始终可以将枚举类型用作字符串。这是一个参考


8

除了不允许您提供不正确的值之外,枚举的另一个特点可能看起来很小,但在我看来相当重要。现代IDE可以自动为枚举建议值,而无法可靠地推断字符串常量的可能值(Intellij IDEA对JDK类和流行库进行后者操作)。当您正在探索新的API时,这尤其有用。


2
枚举类型更能保证类型安全,因为无法输入错误值。但是在Android中,枚举会占用大量内存,建议使用IntDef代替。可以参考此答案的例子和解释:

IntDef/StringDef Example

你也可以查看Android源代码,它在尽可能的情况下都用IntDef/StringDef代替了枚举类型。例如:View.VISIBLE。


-1
我建议你仅在确实需要枚举常量或所有项目都共有的一些额外功能时才使用枚举。
当然,这取决于您正在编写的应用程序类型以及您想要支持的版本和设备。
原因是,枚举会增加开销,因为它们分配其项的实例。您可以注意到,在 Android 平台上有最少的枚举,几乎所有常量都是 final static int(例如 View.GONE 等)。

2
@Jon Skeet:你对此有何看法? - Waqas
3
有时候,类型安全性值得“额外开销”的代价。 - Michael Campbell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接