Java 在多应用程序环境中处理枚举

Java 在多应用程序环境中处理枚举,java,enums,enumeration,Java,Enums,Enumeration,我们的公司主要用Java开发,并支持许多“实时”系统(主要是长时间运行的服务器进程),所有这些系统都依赖于共享的参考数据和枚举。偶尔,枚举定义会扩展以包含新值,在这种情况下,我们当前会重新部署所有应用程序,原因是我们的应用程序都有一个包含所有库jar(包括“枚举实体”库)的私有“lib”文件夹。显然这是不可取的,所以我很想听听其他人的建议或方法 我想到的想法是: 修改每个应用程序的启动脚本以派生最新的“enum entity”库版本,并将jar文件前置到类路径 某种在运行时动态类加载新枚举定义的

我们的公司主要用Java开发,并支持许多“实时”系统(主要是长时间运行的服务器进程),所有这些系统都依赖于共享的参考数据和枚举。偶尔,枚举定义会扩展以包含新值,在这种情况下,我们当前会重新部署所有应用程序,原因是我们的应用程序都有一个包含所有库jar(包括“枚举实体”库)的私有“lib”文件夹。显然这是不可取的,所以我很想听听其他人的建议或方法

我想到的想法是:

  • 修改每个应用程序的启动脚本以派生最新的“enum entity”库版本,并将jar文件前置到类路径
  • 某种在运行时动态类加载新枚举定义的机制
  • 这些方法的问题在于,应用程序通常具有以下格式的代码:

    switch(enumVal) {
      case A:
        // Do something.
        break;
      case B:
        // Do something.
        break;
      default:
        throw new IllegalArgumentException("Invalid enum value: " + enumVal);
    }
    

    。。。因此,当它们遇到默认情况时,就会开始失败。也许这表明这些实体根本不应该是枚举;对我们来说,这确实是一种方便的权衡。或者,这仅仅表明我们的应用程序太脆弱,应该更优雅地处理默认情况。

    史密斯先生是对的:扩展枚举,或者在这方面使用老式的“枚举”int常量,很难做到正确,通常不是一个好方法。

    正如您所暗示的,新的枚举值需要使用它们的客户端进行特殊的行为/处理。修改枚举后,也必须修改客户端。这真的很糟糕,你应该尝试用另一种方式重新设计它。

    面向对象技术就是专门为解决这个问题而发明的:你的开关实际上只是一个显式虚拟表,而隐式虚拟表则要好得多。您应该考虑重新设计应用程序以使用接口/基类而不是枚举。

    这就将问题转移到了对象创建时间,这为每个枚举提供了单个更改点的直接优势。In还为引入基于插件的体系结构开辟了道路,该体系结构可能不需要任何重新编译,甚至可能导致在不重新启动应用程序的情况下扩展应用程序。考虑到您所说的长时间运行的服务器进程,减少停机时间可能很有吸引力


    避免重新编译的最简单方法可能是采用。使用这样的框架,您可以拥有一个或多个配置文件,在其中指定需要创建的对象,然后可以按名称加载它们。

    我认为您必须重新考虑应用程序设计。请记住:封装变化。当枚举定义扩展时,是否所有应用程序都立即开始使用新值?你用这些枚举做什么?如果向枚举添加新值,但不在应用程序代码中的任何位置引用它,应用程序是否仍在使用它(例如使用valueOf())?枚举是编译时常量。因此,仅仅重启是不够的。如果更改枚举中的任何内容,则必须重新编译使用它们的所有类。@Udo Fholl:不完全正确,因为Java在运行时只按名称执行(后期)绑定。如果只将新元素添加到任何类文件(“可见接口”)中,则不需要重新编译现有代码。是的,但即使枚举也可以有方法。您只能使用单级继承层次结构,但它们的行为与常规类几乎相同。对于每个枚举常量方法,也可以有不同的重写。因此,与其对开关或if-else进行编码,不如将要执行的操作移动到每个枚举/类方法中,并从客户机代码中调用它。我再次同意,并可能会补充:如果专门的行为/处理可以在枚举本身的单个位置实现,那么它对所有客户机都是相同的,首先,它不应该在客户端实现。哦,请注意,枚举不支持继承,因此不支持多态性。枚举常量是枚举“类”的一种子类。您可以有一个特定于常量的类主体,以覆盖枚举中为特定枚举常量定义的方法。这不是我所说的干净设计,但它是有效的。没错,但客户端无法派生自己提供的枚举类型的实现来改变行为。这很有趣。让我们想象一下,他有一个合适的OO设计。总有一天,新的需求会被引入,一个新的类(至少)必须被添加。有什么方法可以不用重新编译就将其放入系统中呢?好的,现在我们使用的不是编码工厂,而是XML。但是,新类应该在系统中引入,以便DI框架实例化它,不是吗?不重新编译怎么办?只是在某个文件夹中添加类文件?还有一个问题:DI框架是否检测到XML已被更改,或者需要重新启动?是的,您可以将类文件添加到文件夹或jar中,尽管后者可能会阻止“热”添加。我不熟悉如何自动升级配置的细节,因为我自己从来不需要这样做。