【问题标题】:Declare java enum with a String array用 String 数组声明 java 枚举
【发布时间】:2010-06-07 16:00:02
【问题描述】:

我正在尝试根据从数据库中检索的数据声明枚举类型。我有一个方法,它返回一个字符串数组,该数组包含表中我想变成枚举类型的所有行。有没有办法用数组构造枚举?

这是我尝试过的,但从它在 eclipse 中的样子来看,这似乎只是用那个名称创建了一个方法:

public enum ConditionCodes{
    Condition.getDescriptions();
}

提前谢谢你!

【问题讨论】:

  • 您还可以聪明地编写代码,从数据库中检索值,生成一个使用这些值声明枚举的 .java 文件,然后从那里编译代码。
  • @Sean:是的,这很聪明,但也很脆弱。无论如何,你会失去enum 的大部分优势,那么为什么要花这么多精力来获得这么少的好处呢?
  • 我同意这有点令人费解,但它是关于 Android 应用程序对其资源所做的事情。枚举比比较原始字符串常量(例如 foo.equals("SOMETHING")foo == Things.SOMETHING)要好,因为您可以获得编译时类型检查。这是一种自动维护该枚举的方法。
  • @Sean:我明白,但是通过实现我在答案中链接的类型安全枚举模式的变体,同样可以达到这个目标。这将涉及更少的黑魔法。

标签: java arrays enums


【解决方案1】:

你不能。

enum 的值必须在编译时知道。如果您还有其他内容,则不是enum

您可以通过类似于the old typesafe enums 的实现来接近,在Java 语言通过enum 关键字引入对该技术的支持之前使用该实现。您可以使用这些技术,但只需将 static final 字段替换为从数据库中读取的值。

【讨论】:

  • 我就是这么想的。谢谢!
【解决方案2】:

为了使您的枚举有用,必须在编译时确定它。从数据库查询生成枚举意味着您希望在运行时看到新的枚举值。即使您创建了一个代码生成器来使用数据库查询动态创建枚举类,您也无法在代码中引用这些枚举值,而这正是拥有它们的意义所在。

【讨论】:

    【解决方案3】:

    很难看出任何编译器如何支持这一点。

    枚举的全部意义在于您可以在编译时检查值的有效性。例如,如果您声明一个枚举“enum MyStatusCode {FOO, BAR, PLUGH}”,那么在您的代码中,如果您编写“MyStatusCode.FOO”,一切都很好,但如果您编写“MyStatusCode.ZORK”,您会得到一个编译 -时间错误。这可以保护您避免拼写错误的值或对一个枚举与另一个枚举的值混淆。 (我最近遇到了一个问题,程序员不小心将交付方式分配给了交易类型,因此当他打算将送货上门更改为客户自提时,神奇地将销售更改为库存调整。)

    但是如果你的值是在运行时动态定义的,编译器怎么能做到这一点呢?如果您在上面的示例中编写了 MyStatusCode.ZORK,编译器无法知道该值在运行时是否会出现在数据库中。即使您想象一个足够聪明的编译器来弄清楚枚举是如何被填充的并检查数据库以查看该值是否现在存在于适当的表中,它也无法知道当您实际运行时它是否存在.

    简而言之,你想要的是与枚举非常不同的东西。

    【讨论】:

      【解决方案4】:

      如果你想真正疯狂,我认为annotation processing 可以做到这一点。注释处理让您可以挂钩编译器,并在您的 @annotation 存在时让它神奇地修改内容。

      自然,枚举中的值将是编译时可用的任何值。

      【讨论】:

        【解决方案5】:

        不,这是不可能的,因为枚举类型必须在编译时定义,而您正在寻找的是动态创建它。

        如果改用类,也许你会更好。

        【讨论】:

          【解决方案6】:

          我认为在这里您将需要一个 List 或 Set 以及一些用于搜索和比较的实用方法。

          这是你的清单

          List<String> conditionCodes = new ArrayList<String>();
          //Somehow get Rows or POJO Beans from database with your favorite framework
          Collection<Row> dbRows = getConditionCodes();
          for(Row curRow : dbRows)
               conditionCodes.add(curRow.getName());
          

          搜索

          public boolean conditionExists(String name) {
              return conditonCodes.contains(name);
          }
          
          public String getCondition(String name) {
              return conditionCodes.get(name);
          }
          

          (当然你可能想要使用 List 自己的方法而不是自己制作)

          【讨论】:

            【解决方案7】:

            除了你不能,你不想。每个枚举,甚至是 Java 相当酷的枚举,都是面向代码的。

            它与集合完全相同,但使用枚举时,您往往会在遇到它时编写重复的代码——使用集合您更有可能编写循环。

            我建议您使用私有构造函数创建一个类并让它创建自己的实例,然后提供一个 getInstance(String) 来检索实例。这就像旧的类型安全枚举模式。

            然而,从长远来看,如果您能够设法获得足够的智能到您永远不会区分特定实例的那个类中,那就更好了——不同于“枚举”的做法:

            if(myEnum.stringValue.equals("EnumTarget"))
                executeCode();
            

            以面向对象的方式来做:

            myEnumLikeObject.executeCode();
            

            将您希望的代码移动到“枚举”中——最好直接委托给在创建时实例化并设置到“枚举”中的包含对象。

            【讨论】:

              猜你喜欢
              • 2018-05-30
              • 1970-01-01
              • 2011-10-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多