Java 5+中的静态字符串常量与枚举类型比较

25
我阅读了以下问题和答案:什么是在Java中实现常量的最佳方法?

我得出结论,枚举(enum)是实现一组常量的更好方式。我还阅读了Sun网站上有关如何向枚举添加行为的示例(请参见先前提到的帖子中的链接)。 因此,在枚举中添加具有字符串键的构造函数来保存一系列字符串值不是问题。

这里唯一的问题是我们需要添加“.nameOfProperty”才能访问字符串值。 因此,在代码的任何地方,我们需要引用常量值,不仅要通过名称(EnumName.MY_CONSTANT),而且要像这样(Enum.MY_CONSTANT.propertyName)。

我的理解正确吗? 你对此有何看法?


你能澄清一下问题吗?你是在使用成员变量而不是访问器函数吗? - Michael Aaron Safyan
无论如何。比如,访问器函数。此外还提供()。 问题是关于冗长性的,正如KLE和N. Fortescue所写的那样。 但是正如被告知的那样,我可以重写toString(有趣的决定),最重要的是,我可以看到在这里使用枚举可能是一个好的实践。 - EugeneP
对于我和许多人来说,toString() 应该是一个调试字符串(在调试、技术日志等方面非常有用)。在应用程序的正常过程中使用它的问题在于,有一天,有人会重写它以显示更多的调试信息,认为这不会影响应用程序的行为。 - KLE
嗯,有趣。这里的问题是这个结构(枚举)将用于保存字符串,而不是其他任何东西。通常我可以理解对象只应将其用于调试目的,但在这种情况下并非如此,你不认为吗?在我看来,我们的枚举有点像一个字符串对象!因此,当我们谈论字符串对象时,我们不使用它的toString方法进行调试!我正确吗? - EugeneP
1
Java的toString的目的是提供“简明但信息丰富,易于人阅读的表示形式”。虽然有些人使用它来调试代码,但这违反了合同,不应被认为是正确的。将其用于创建可打印版本是正确的用法。如果您以正确的方式使用toString,则不必担心某天会有人做错事情。那总是可能发生的,那么你最好什么也不做。 - Jasper Floor
显示剩余2条评论
2个回答

25

是的,枚举类的命名可能会显得有点长。但并没有想象中那么长...

  1. 因为枚举类已经提供了一些上下文信息("这个常量集合属于哪个?"),实例名称通常比常量名称短(强类型已经将其与其他枚举中同名的实例区分开)。

  2. 此外,您可以使用静态导入来进一步缩短长度。您不应该在所有地方都使用它,以避免混淆,但我认为与枚举紧密关联的代码可以使用它。

  3. 在枚举的switch语句中,您不使用类名称。(在Java 7之前甚至不能在字符串上使用switch)。

  4. 在枚举类本身中,您使用短名称。

  5. 由于枚举具有方法,许多低级代码可能会从业务代码迁移到枚举类本身(无论是动态方法还是静态方法)。正如我们所看到的,将代码迁移到枚举甚至可以进一步减少长名称的使用。

  6. 常量通常以组的形式处理,例如一个if,它测试与六个常量中的一个是否相等,或其他四个常量等。枚举配备了EnumSet和contains方法(或类似的动态方法,返回适当的组),让您可以将组作为组处理(作为次要优点,注意这两种分组实现非常快-O(1)-并且低内存!)。

有了所有这些观点,我发现实际代码要短得多


7

关于常量的问题 - 枚举应该表示相同类型的常量。如果您正在进行任意常量,那么这是错误的方法,原因在另一个问题中都有描述。

如果您只想要字符串常量,并且考虑到冗长的代码,您是正确的。但是,您可以重写toString()方法返回属性的名称。如果您只想将字符串连接到其他字符串,则这将为您的代码节省一些额外的冗余。

然而,您是否考虑过使用属性文件或其他国际化手段?通常在定义字符串集时,这是针对用户界面消息的,将其提取到单独的文件中可能会为您节省大量未来的工作,并使翻译更加容易。


1
在覆盖toString()方法方面,我认为任何开发人员都可以随时使用它来在调试中显示更多信息(也适用于技术日志)。如果您的实际应用程序行为依赖于它,则代码将会崩溃,缺乏健壮性。 - KLE
关于在最终用户消息中使用属性,肯定是可以的!无论如何,实例名称不能使用特殊字符,必须全部大写并用“_”分隔(就像所有常量一样)...因此它们不能用于最终用户消息。 - KLE
再次强调,使用toString进行代码调试是不正确的用法。遵循API契约,您的代码将更加健壮。违反契约,您的代码将变得不够健壮。 - Jasper Floor
枚举应该表示所有相同类型的常量-有用的备注。 - EugeneP

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