代码之家  ›  专栏  ›  技术社区  ›  Vance Brockberg

使用标记接口在Java中实现伪枚举继承

  •  1
  • Vance Brockberg  · 技术社区  · 2 年前

    我用的是 Marker Interface 实现伪枚举继承。

    假设我定义Marker类如下:

    public interface FieldInterface
    

    现在我有5个枚举类来实现这个接口。

    enum Field1 implements FieldInterface
    enum Field2 implements FieldInterface
    enum Field3 implements FieldInterface
    enum Field4 implements FieldInterface
    enum Field5 implements FieldInterface
    

    上面的5个枚举“Field”类中的每一个都定义了与该字段类型相关的枚举列表。例如,枚举 Field1 可能定义枚举: Field1A, Field1B, Field1C .枚举 Field2 可能定义枚举: Field2A, Field2B, Field2C

    现在,我需要将每个枚举的纯文本表示转换为相应的枚举(类似于调用 enum.valueOf(String) ) 不知道字符串属于5个枚举类中的哪一个

    实现这一目标的一种方法可能是 reflection 首先检索实现所述接口的所有类的列表,并遍历所有5个枚举类,直到找到匹配项。然而,如果可能的话,我宁愿避免反思(主要是由于性能原因)。

    还有什么其他选择可以解决这个问题?

    谢谢

    0 回复  |  直到 2 年前
        1
  •  2
  •   Delta George    2 年前

    地图的传统实现<字符串,枚举(<&燃气轮机&燃气轮机;处理多个枚举类的复杂性很小。静态最终映射实例在接口中定义,并在所有枚举中共享。

    import java.util.HashMap;
    import java.util.Map;
    import java.util.stream.IntStream;
    
    class Main {
    
        public static void main(final String[] args) {
            // Enum classes must be loaded
            loadEnums();
    
        System.out.println(X.get("FIELD1B"));
        ((X) () -> "FIELD1B").add();    // Attempt to pollute the map is blocked
        System.out.println(X.get("FIELD1B"));
        }
    
        private static void loadEnums() {
            IntStream.range(1, 10).mapToObj(n -> Main.class.getPackageName() + ".Main$Field" + n).forEach(Main::loadEnum);
        }
    
        private static void loadEnum(String name) {
            try {
                Class.forName(name);
            } catch (ClassNotFoundException e) {
            }
        }
    
        /**
         * All enums implement this marker interface and therefore share access to a static map from the name of the enum to its value.
         */
        interface X {
            Map<String, X> map = new HashMap<>();
    
            /**
             * This shared method uses enum's name method to get enum's string representation.
             */
            default void add() {
              if (this instanceof Enum<?>) {
                  map.put(name(), this);
              }
            }
    
            static X get(String key) {
                return map.get(key);
            }
    
            /**
             * This method is always overwritten by each enum because all enums have a name() method.
             */
            String name();
        }
    
        enum Field1 implements X {
            FIELD1A, FIELD1B, FIELD1C;
    
            // We have to call add() to place each enum value in the shared map
            Field1() {
                add();
            }
        }
    
        enum Field2 implements X {
            FIELD2A, FIELD2B, FIELD2C;
    
            Field2() {
                add();
            }
        }
    }