存储常量的最佳方式,无论是枚举表还是数据库表,都要考虑国际化



我有很多静态/常量数据要存储,这些数据也是相互关联的。我可以使用多个枚举相互引用来形成树或图。或者简单地使用表或数据库枚举并在其中存储值,并创建相应的类和相应的关系。我掌握的数据是不变的,肯定不会改变。在不久的将来,我可能还必须考虑国际化。我将使用这个常量数据作为各种其他数据的过滤器。

我很想使用枚举,因为默认情况下它给了我不变性,但看到数据之间关系的复杂性,就像我可能不得不牺牲继承一样,我对枚举也不太担心。从数据库和国际化中填充这些枚举类可能会稍微复杂一些。在后期阶段,希望它能轻松扩展并接受复杂性是我关注的领域,因为我不想从中途恢复。!

---更新---

我还没有看到枚举彼此相关(关联)的示例,其中包含引用其他枚举的复杂类型的字段。在这种情况下,当数据为常量时,枚举可以替换类。有什么客观的方法来看待这个问题吗。

为了更好地理解,我有类似的分类如下。具有树层次的动物王国

虽然这个问题对于Stack Overflow来说可能太宽泛了,但有一些想法。

枚举

您可能不完全理解Java中的枚举功能。请参阅Oracle教程,并参阅Enum类文档。

枚举一个类,一个常规Java类,Enum的子类。唯一特别的是语法糖,它自动实例化您定义和命名的静态实例。否则,它们是正常类:

  • 枚举可以携带成员变量
  • 枚举可以有构造函数,并且可以将参数传递给这些构造函数
  • 枚举可以提供其他方法,并且可以将参数传递给这些方法
  • 您甚至可以将一个枚举的实例作为参数传递给另一个枚举实例的方法,就像将枚举的实例传递给其他非枚举类的实例一样。每个枚举实例只是一个对象,简单明了,保存为枚举定义类上的静态引用

示例:

public enum Food { HERBIVORE, OMNIVORE, CARNIVORE ; }  // Syntactic sugar for automatically instantiating these named static instances of this class type.

…和…

public enum Animal {
RABBIT( Food.HERBIVORE ) , 
DOG( Food.OMNIVORE ) , 
CAT( Food.CARNIVORE ) ;  
// Member variables.
public Food eats ; 
// Constructor
Animal( Food foodType ) {
this.eats = foodType ;  // Assign an instance of another enum to this instance of this enum.
}
}

枚举的限制

虽然比其他语言更强大、更有用,但也有局限性。

编译时间

首先,枚举是在编译时定义的。如果您的值在运行时发生更改,也许您想添加或删除项,那么枚举是不合适的。

永久存储在内存中

此外,枚举是静态的。这意味着当第一次使用时,该枚举类的所有对象都会立即实例化,并在应用程序的整个执行过程中保存在内存中。所以在程序结束之前,它们永远不会从内存中退出。因此,拥有大量的它们可能会给记忆带来负担。

了解您可以收集枚举实例。有关枚举实例的快速执行和低内存使用率集合,请参阅EnumSetEnumMap类。搜索堆栈溢出以获取有关此主题的大量报道。请注意,每个枚举都携带一个values()方法,该方法返回其值的数组,但该方法神秘地没有在JavaDoc中列出。

至于您提到的继承,您的枚举根据定义是Enum类的子类。因此,它们不能从您可能想到的任何其他类继承,因为Java不支持多重继承。您的枚举可以实现一个或多个接口。在Java的后期版本中,继承可以通过新的默认方法携带实现代码,因此您可以通过这种方式传递一些代码。

国际化

国际化和本地化似乎是一个正交的问题。您可以在枚举上添加一个方法来生成其值的本地化String表示。例如,请参见DayOfWeek::getDisplayNameMonth::getDisplayName枚举方法。

数据库

如果你想在运行时动态定义你的值,或者你有无数的值,那么数据库就是你的选择。像Postgres这样严肃的数据库是为了管理内存、处理并发和高效执行而设计的。

您甚至可以将枚举与数据库结合起来。例如,本地化。您可能在编译时定义了枚举值,但它们的getDisplayName方法会在数据库中查找法语或阿拉伯语翻译。数据库中的转换值可以在运行时通过JDBC运行SQLINSERTUPDATE命令来更新。

递归层次关系

如果你试图表示任意深度的层次结构的关系,这是我在这里不讨论的另一个主题,除了说它通常是用递归实现的。搜索堆栈溢出和其他来源以了解更多信息。

根据经验,只有当值的更改速度可能快于代码发布周期,并且可能或可能有非我的人将更改它们时,我才会涉及数据库。使代码依赖于一个正在运行(并且可用)的数据库意味着,当某个DBA为了维护数据库而关闭数据库时,您的应用程序就无法启动。

最新更新