简体   繁体   English

将一种枚举类型转换为另一种枚举类型的通用方法

[英]Generic method to convert one enum type to another

I have two enum as below我有两个枚举如下

First第一的

public enum firstEnum {
    ALL_PRODUCT,
    SPECIFIC_COLLECTION,
    SPECIFIC_PRODUCT
}

second第二

public enum secondEnum {
    PRODUCT,
    COLLECTION,
    PRODUCT
}

I am trying to create a generic method to convert one type to another as below我正在尝试创建一个通用方法来将一种类型转换为另一种类型,如下所示

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

Not sure how can I achieve this, any help will be appreciated.不知道我怎样才能做到这一点,任何帮助将不胜感激。 firstEnum.ALL_Product should return secondEnum.Product, firstEnum.SPECIFIC_COLLECTION should return secondEnum.COLLECTION

Here's one way to do it.这是一种方法。

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

If you want to have multiple mappings from the same enum, you can use EnumMap<E1, E2> to capture the mapping.如果要从同一个枚举中获得多个映射,可以使用EnumMap<E1, E2>来捕获映射。 Build the EnumMap in the constructor of E1 using the same technique.使用相同的技术在 E1 的构造函数中构建EnumMap This way, the mapping between enums is explicit.这样,枚举之间的映射是明确的。

Trying to do the mapping implicitly based on ordinals, as another answer suggested, is a world of hurt.正如另一个答案所建议的那样,试图基于序数隐式地进行映射是一个伤害世界。 If someone asks about the wrong pair of enums, you will either get a garbage answer or an exception when one has more constants than the other.如果有人询问错误的一对枚举,当其中一个具有比另一个更多的常量时,您将得到一个垃圾答案或异常。 And even if they use it correctly, if someone later inserts a new enum constant into one and doesn't insert it in the exactly right place in the other, your code is broken.即使他们正确地使用它,如果有人稍后将一个新的枚举常量插入其中,并且没有将它插入到另一个的完全正确的位置,那么您的代码就会被破坏。

If you want to be doing this kind mapping, the two classes are coupled, and you have to capture that coupling somewhere, either in the type system ( implements ) or as explicitly initialized data ( EnumMap ).如果你想做这种映射,这两个类是耦合的,你必须在某个地方捕获这种耦合,无论是在类型系统( implements )中还是作为显式初始化的数据( EnumMap )。

I think TacheDeChoco is on the right track, but he misses the necessary generics declarations.我认为 TacheDeChoco 是在正确的轨道上,但他错过了必要的 generics 声明。 Also, since generics are implemented through type erasure, you need to pass in the class of the second enum type.另外,由于 generics 是通过类型擦除实现的,因此需要传入第二种枚举类型的 class。

Assuming the mapping strategy is as simple as "taking the corresponding enum values being at the exact same position" , the following could to the job:假设映射策略就像“将相应的枚举值放在完全相同的位置”一样简单,那么可以完成以下工作:

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

Assuming the mapping strategy is as simple as "taking the corresponding enum values being at the exact same position ", the following could to the job:假设映射策略就像“将相应的枚举值与完全相同的 position ”一样简单,则可以执行以下操作:

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

Considering that you need return the value of the same position of second Enum, you can try this:考虑到您需要返回第二个 Enum 的相同 position 的值,您可以试试这个:

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
}

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

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