繁体   English   中英

如何在 Java 中获取 static class 成员的枚举?

[英]How to get an enum of static class members in Java?

我有一个 Java class(我不控制也不能修改)它有大量的 static String 成员。 我怎样才能将这些作为枚举(为了编码方便)?

例如我有:

public class ClassWithStaticMembers {
  public static String ONE = "one";
  public static String TWO = "dos";
}

...我想从中得出以下结论:

public enum NUMBERS {
  ONE,
  TWO
}

这是可能的,有反射或其他方式吗?

(假设我不太了解 Java,并且我有 100 多个值,所以重复每个值是痛苦的,也是不可取的(以防以后添加更多值)。而且我不需要 class 中的实际值(“一个”和上面的“dos”))。

为简单起见:枚举是静态描述的,因此不可能通过反射创建它。

您仍然可以创建一个枚举来包装您的常量,并且可以选择进行单元测试(使用反射)以确保您的枚举是完整的。

public enum NumbersEnumeration {
  ONE(ClassWithStaticMembers.ONE),
  TWO(ClassWithStaticMembers.TWO);
  private static final String name;
  public String getName(){return name};
  public NumbersEnumeration(String name){this.name=name;}
}


public class NumbersEnumerationTest{

  @Test
  public void checkEnumComplete() throws Exception{
    var fields = List.of(ClassWithStaticMembers.class.getDeclaredFields());
    for( var field:fields){
      Assertions.assertNotNull(NumbersEnumeration.valueof(field.getName());
    }
  }
}

(反射可能存在编译问题,但你明白了)

您可以使用Class.getDeclaredFields()获取表示由 class 定义的字段的java.lang.reflect.Field实例,并过滤掉标记为static的字段并访问它们的值。

问题是getDeclaredFields()保证它返回的数组将以任何特定方式排序。 这是文档中的引述:

返回数组中的元素未排序未按任何特定顺序排列

因此,如果您正在考虑根据声明的顺序自动关联 static 字段和枚举成员,那是行不通的,反射 API 在这里帮不上忙。

我建议引入一个单独的实用程序类,它将包装一个Map关联字符串值和枚举常量。

public class NumbersUtils {
    public static final Map<String, Numbers> NUMBERS = Map.ofEntries(
        Map.entry("one", Numbers.ONE),
        Map.entry("dos", Numbers.TWO),
        ...
    );
    
    private NumbersUtils() {} // utility classes are not meant to be instantiated

    public static Numbers toNumber(String str) {
        if (!NUMBERS.containsKey(str)) throw new IllegalStateException(); // or remove this line if you don's want to throw in such case, method would return null instead
        
        return NUMBERS.get(str);
    }
}

即使您有可能修改枚举,最好将此逻辑保留在枚举之外,而在枚举内您可以引入一个委托给NumbersUtils.toNumber()的方法

旁注:

  • 如果代码中的这些 static 字符串和枚举在不同语言中表示相同的东西,并且它们旨在促进应用程序的国际化,那么保留硬编码字符串您可能希望熟悉正确的 I18N 技术(通过properties文件和ResourceBundle包)。 本教程将给出关于该主题的总体思路。

  • 在编写代码时尽量遵守[Java 语言命名约定][约定]。 名称枚举(以及类和接口)应该更新为大写。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM