【问题标题】:Generic method to convert one enum type to another将一种枚举类型转换为另一种枚举类型的通用方法
【发布时间】:2021-05-21 12:39:16
【问题描述】:

我有两个枚举如下

第一

public enum firstEnum {
    ALL_PRODUCT,
    SPECIFIC_COLLECTION,
    SPECIFIC_PRODUCT
}

public enum secondEnum {
    PRODUCT,
    COLLECTION,
    PRODUCT
}

我正在尝试创建一个通用方法来将一种类型转换为另一种类型,如下所示

public record EnumCasting() {
    public <E1,E2> E2 CastOneEnumToAnother(E1 enumFirst, E2 enumSecond) {
         return // some logic to convert
    }
}

不知道如何实现这一点,任何帮助将不胜感激。 firstEnum.ALL_Product should return secondEnum.Product, firstEnum.SPECIFIC_COLLECTION should return secondEnum.COLLECTION

【问题讨论】:

  • e1的逻辑第一个值=e2的第一个值等等应该是什么?
  • 返回类型是E2,所以我需要返回第二个值。
  • 我的意思是转换应该如何工作? firstEnum.ALL_Product 应该返回 secondEnum.Product,firstEnum.SPECIFIC_COLLECTION 应该返回 secondEnum.COLLECTION ... 为什么你有两个枚举作为参数?
  • @Jens 是的,你是正确的 firstEnum.ALL_Product 应该返回 secondEnum.Product
  • 如果我将两种不同的枚举类型传递给您的方法,结果应该是什么?如果第一个是 { SUN, MON, TUE, WED, THU, FRI, SAT } 而另一个是 { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY },那么我很难想象 Java 代码会猜到我可能希望将 SUN 映射到 SUNDAY 等。

标签: java generics java-8 enums


【解决方案1】:

这是一种方法。

interface MappableEnum<E> { 
    E counterpart();
}

enum E1 {
    A, B, C;
}

enum E2 implements MappableEnum<E1> {
    AA(E1.A), BB(E1.B), CC(E1.C);

    private final E1 counterpart;

    E2(E1 counterpart) { this.counterpart = counterpart; }

    E1 counterpart() { return counterpart; }
}

如果您想拥有来自同一个枚举的多个映射,您可以使用EnumMap&lt;E1, E2&gt; 来捕获映射。使用相同的技术在 E1 的构造函数中构建EnumMap。这样,枚举之间的映射是明确的。

正如另一个答案所暗示的那样,尝试基于序数隐式进行映射是一个伤害世界。如果有人询问错误的枚举对,当其中一个具有比另一个更多的常量时,您将得到一个垃圾答案或异常。即使他们正确使用它,如果后来有人在其中插入一个新的枚举常量,但没有将它插入到另一个的完全正确的位置,你的代码就会被破坏。

如果你想进行这种映射,这两个类是耦合的,你必须在某个地方捕获这种耦合,无论是在类型系统 (implements) 中还是作为显式初始化数据 (EnumMap)。

【讨论】:

    【解决方案2】:

    我认为 TacheDeChoco 是在正确的轨道上,但他错过了必要的泛型声明。另外,由于泛型是通过类型擦除实现的,所以需要传入第二种枚举类型的类。

    假设映射策略就像“将对应的枚举值放在完全相同的位置”一样简单,那么可以做到以下几点:

    public record EnumCaster() {
        public static <E1 extends Enum<E1>, E2 extends Enum<E2>> E2 CastOneEnumToAnother(E1 input, Class<E2> e2) {
            int pos = input.ordinal();
            return e2.getEnumConstants()[pos];
        }
    
        public static void main(String[] args) {
            System.out.println(firstEnum.ALL_PRODUCT);
            System.out.println(CastOneEnumToAnother(firstEnum.ALL_PRODUCT, secondEnum.class));
        }
    }
    

    【讨论】:

      【解决方案3】:

      考虑到你需要返回第二个Enum相同位置的值,你可以试试这个:

      public class Main {
      
          public static void main(String[] args) throws Exception {
      
              SecondEnum selectedEnum = castOneEnumToAnother(FirstEnum.ALL_PRODUCT, SecondEnum.values()); // ok
              System.out.println("Selected enum: " + selectedEnum);
      
              selectedEnum = castOneEnumToAnother(FirstEnum.SPECIFIC_PRODUCT, SecondEnum.values()); //exception
              System.out.println("Selected enum: " + selectedEnum);
          }
      
          public static <E1 extends Enum<E1>, E2 extends Enum<E2>> E2 castOneEnumToAnother(E1 enumInput, E2[] enumValues) throws Exception {
              int pos = enumInput.ordinal();
      
              if (pos >= enumValues.length) {
                  throw new Exception("Not found value in position " + pos + " for " + enumValues[0].getDeclaringClass().getSimpleName());
              }
              return enumValues[pos];
          }
      }
      
      enum FirstEnum {
          ALL_PRODUCT, SPECIFIC_COLLECTION, SPECIFIC_PRODUCT
      }
      
      enum SecondEnum {
          PRODUCT, COLLECTION //, PRODUCT
      }
      

      【讨论】:

        【解决方案4】:

        假设映射策略就像“将对应的枚举值放在完全相同的位置”一样简单,那么可以完成以下工作:

        public record EnumCasting() {
            public <E1 extends Enum<E1>, E2 extends Enum<E2>> E2 CastOneEnumToAnother(
                    E1 input, Class<? extends E2> e2Class) {
                int pos = input.ordinal();
                return e2Class.getEnumConstants()[pos];
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2010-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多