使用字符串或int引用系统的Java部分之外的枚举更好吗?


11

我们在工作中讨论了Java中枚举的使用。

一位同事争辩说,在服务器端使用枚举时,每当需要时,我们都应该使用字符串来引用它(例如,当从JS向服务器发送数据或存储在数据库中时),认为这更加清楚了。对于开发人员来说也很困难,如果出现拼写错误,它将很快失败。

在这些情况下,我总是使用整数来标识枚举,因为它是不可变的标识符,并且不会出现大小写和拼写错误(即使开发人员错误地使用了值2而不是1,也不会很快失败)。

对这些参数非常分析,我会说使用字符串会更好,但是我对此有一种奇怪的感觉(好像这不是一个好方法)。

关于此讨论,是否有任何最佳实践可以指导我?

编辑:只要有可能,我们就使用枚举本身,因此我们所有的Java代码都使用枚举。“引用枚举”的意思是:在将数据从JavaScript交换到服务器或将数据存储在数据库中时,引用枚举中的值


1
什么是“引用枚举”?在源代码中正常使用?用于存储在数据库中的序列化?在用户文档中使用表达式?表示要在技术文档中使用?对于所有这些人,答案将完全不同。
Kilian Foth,2014年

我已经编辑了问题,希望现在可以更清楚了:通过“引用枚举”,我的意思是在将数据从JavaScript交换到服务器或以其他方式在数据库中存储值时引用值
JSBach

在javascript API中,我当然会使用字符串。在DB中都有各自的优势。一些数据库内置了枚举支持。
CodesInChaos 2014年

Answers:


15

好问题。在Java中使用枚举主要是为了处理本质上属于绝对类别的信息。经典示例是使用枚举来处理卡片可能具有的四种西服类型。它提供了使用整数的所有性能优势,并且在程序中也很明显。

因此,在Java之外,为什么不继续使用整数?也许您在Java之外没有枚举类型,但这并不意味着您不能出于性能目的继续使用整数,对吗?是的,这是完全正确的,尽管考虑添加新的枚举值时会发生什么。如果不将其添加到末尾,则新值之后的所有其他枚举值将增加一个。好吧,我们只指定数字,这样它就不会更改,或者总是将其添加到末尾。您有信心您的同事会一直这样做吗?嗯 大概?希望?也许您对此不是100%。请记住这一点。

您的老板告诉您,上次更新后使用您的软件的客户端出现混乱。现在,所有实体X的行为就好像它们被分配了枚举值Y一样,即使它们实际上确实被分配了Z。您检查存储库,是的,有人添加了一个新的枚举值,并且没有按照您的要求遵循您的准则。现在,您又增加了一个复杂性,即在数据库上将其写为4,而实际上应为3,不包括在更新之前插入的记录,实际上 4。无论如何,枚举值与4有关?是不是 你不记得了 您需要检查程序进行验证。简而言之,就是一团糟。

相反,如果您的数据库写了“ HEARTS”,“ DIAMONDS”,“ SPADES”,“ CLUBS”,那么您在空间方面几乎没有损失,却收获了很多。的确,我们所说的是对性能的次要影响,但是您实际上不应该访问经常有所作为的数据库。至于空间,请留给系统管理员(而不是您的问题)。

如果您编写了一个易于更改的简单程序,那么从长远来看,您就已经对自己有所帮助了,请相信我。在我的拙见中,这方面没有什么不同。


2
很好,但是您忘了有人决定更改枚举实体之一的名称(在您的示例中HEARTSHeart或某物),突然之间一切再次中断的情况。
Scott Whitlock 2014年

1
@ScottWhitlock如果您考虑到这一点,则不会,尽管他们可以决定完全重命名它。他们可能会意外删除数据库并删除项目,但是我们无法在此处说明所有可能的事件。
尼尔2014年

5
@Neil-是的,但是我们试图在这里发挥作用。我不熟悉Java枚举,但是在C#中,如果值需要在程序外部(例如在数据库中)具有含义(例如Hearts = 1,Diamonds = 2等),我会明确设置枚举的值。 。由于这不是使用枚举的默认方式,因此应在以后的编辑器中暂停。加上一条注释,指出在其他地方还可以方便使用。
Scott Whitlock 2014年

1
@ScottWhitlock绝对是避免此类问题的更好方法。尽管假设您这样做了,但是您仍然在数据库上看到了1、2、3、4,或者在某些文件中对其进行了序列化。从维护的角度来看,以任何方式对其进行切片都不理想。
尼尔2014年

2
如果我可以添加,如果枚举被序列化为字符串,并且有人更改了枚举的名称,那么在反序列化期间,错误将是在解析期间。如果枚举为int且有人更改了定义,则错误将在处理过程中更进一步,更难以诊断。CC @ScottWhitlock。
Endy Tjahjono

1

我同意尼尔的回答,但只是补充:

在Java中,枚举是对象,因此它们可以具有字段和方法。因此,您可以为每个枚举指定一些手动指定的值,并在外部工作中引用它时,请改用该值。

它在添加/删除/重新排序以及更改枚举实例的名称后都将保留下来。但是您将不得不为枚举字段编写序列化/反序列化逻辑,而不是使用许多工具中提供的automagic。(这很容易,但是它有辅助性的工作)。

而且,您必须手动保持这些值唯一(但是在C样式枚举中是相同的),并且可以编写test进行检查。


是的,我们走了这条路,但是我们使用的是休眠模式,我们不得不添加一些额外的代码才能解析数据库中的值,这似乎有些奇怪,因此我们决定使用.STRING关系和使用枚举名称。
JSBach 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.