代码之家  ›  专栏  ›  技术社区  ›  San Jaisy

Java 16通用方法,用于将一种枚举类型转换为另一种

  •  0
  • San Jaisy  · 技术社区  · 5 年前

    我有两个枚举,如下所示

    弗斯特

    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

    0 回复  |  直到 5 年前
        1
  •  8
  •   Brian Goetz    5 年前

    这里有一种方法。

    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<E1, E2> 以捕捉映射。构建 EnumMap 在E1的构造函数中使用相同的技术。这样,枚举之间的映射是显式的。

    正如另一个答案所暗示的那样,试图基于序数隐式地进行映射是一个充满伤害的世界。如果有人问错了一对枚举,你要么会得到一个垃圾答案,要么会在一个枚举的常量比另一个枚举多的情况下得到一个异常。即使他们正确地使用了它,如果有人后来在一个枚举常量中插入了一个新的枚举常量,而在另一个枚举中没有将其插入到正确的位置,那么你的代码就会损坏。

    如果你想进行这种映射,这两个类是耦合的,你必须在类型系统中的某个地方捕获这种耦合( implements )或者作为明确初始化的数据( EnumMap ).

        2
  •  1
  •   Thomas Kläger    5 年前

    我认为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
  •  0
  •   David B G Dutra    5 年前

    考虑到你需要返回第二个枚举的相同位置的值,你可以尝试这样做:

    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
  •  0
  •   Anonymous    5 年前

    假设映射策略很简单 “将相应的枚举值取在完全相同的位置 “,以下内容可能适用于该作业:

    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];
        }
    }