有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java泛型方法将一种枚举类型转换为另一种枚举类型

我有两个枚举,如下所示

首先

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


共 (4) 个答案

  1. # 1 楼答案

    考虑到需要返回第二个枚举的相同位置的值,可以尝试以下操作:

    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
    }
    
  2. # 2 楼答案

    这里有一个方法

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

    正如另一个答案所暗示的那样,试图隐式地基于序数进行映射是一种伤害。如果有人询问错误的一对枚举,您将得到一个垃圾答案,或者当一个枚举的常量多于另一个枚举时出现异常。即使他们正确地使用它,如果后来有人在其中插入了一个新的枚举常量,而没有在另一个中的正确位置插入它,那么您的代码就被破坏了

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

  3. # 3 楼答案

    我认为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));
        }
    }
    
  4. # 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];
        }
    }