如何在Java中将一个枚举类型的值转换为另一个枚举类型?

23

我该如何在Java中将Enum1的值转换为Enum2?以下是我正在尝试的示例:

public enum Enum1 {
  ONE,
  TWO,
  THREE;
}

public enum Enum2 {
  FOUR,
  FIVE,
  SIX;
}

所以我想做这样的事情:

Enum2 en2 = (Enum2)ONE;

这是否可能,如果可能的话,我应该如何做呢?

先行致谢!


7
当你将Enum1.ONE进行“强制转换”为en2时,你期望en2保持什么值? - Joachim Sauer
11个回答

39

你不能从一个枚举类型直接转换为另一个枚举类型,不过每个枚举类型都有保证的顺序,并且可以轻松地将一个枚举类型翻译成另一个枚举类型(保留顺序)。例如:

enum E1 {
    ONE, TWO, THREE,
}

enum E2 {
    ALPHA, BETA, GAMMA,
}

我们可以通过以下方式将E1.TWO翻译为/从E2.BETA

static E2 E1toE2(E1 value) {
    return E2.values()[value.ordinal()];
}

static E1 E2toE1(E2 value) {
    return E1.values()[value.ordinal()];
}

22

答案取决于"casting"应该做什么......

按序数位置进行转换

在提供的示例中,两组枚举值之间没有共同点,因此我假设意图是按序数位置进行转换,所以 Enum1.ONE => Enum2.FOUREnum1.TWO => Enum2.FIVEEnum1.THREE => Enum2.SIX。可按以下方式完成:

Enum2 en2 = Enum2.values()[Enum1.ONE.ordinal()];

一个自然的后续问题是如何将其扩展到通用函数,以便为任何两个枚举类型执行相同的操作。这不是一件容易的事情,但可以使用Google Guava库完成。
public <F extends Enum<F>> F castByOrdinal(Enum<?> e, Class<F> fClass) {
    return Iterators.get(EnumSet.allOf(fClass).iterator(), e.ordinal());
}

如果没有使用Guava,可以通过几行更多的代码手动完成:

public <F extends Enum<F>> F castByOrdinal(final Enum<?> e, final Class<F> fClass){
    final Iterator<F> iter = EnumSet.allOf(fClass).iterator();
    int count = 0;
    F fValue = null;
    while (count <= e.ordinal()) {
        if (!iter.hasNext()) {
            return null; // ...Or throw an exception e.g. IndexOutOfBoundsException
        }
        fValue = iter.next();
        count++;
    }

    return fValue;
}

使用示例:

Enum2 en2 = castByOrdinal(Enum1.ONE, Enum2.class);

使用共享枚举值名称进行类型转换

另一种可能的枚举类型转换方式是使用一些相同的值名称。

例如:

enum Shape {
    TRIANGLE, SQUARE, PENTAGON, HEXAGON, UNKNOWN, NOT_APPLICABLE
}

enum Size {
    SMALL, MEDIUM, LARGE, UNKNOWN, NOT_APPLICABLE
}

强制转换只适用于常见值(即上面的UNKNOWNNOT_APPLICABLE),可以按以下方式执行:

Size size = Size.valueOf(Shape.UNKNOWN.name());

如果目标枚举中不存在值名称,则会抛出IllegalArgumentException。 此强制转换的通用方法稍微简单一些:

public <F extends Enum<F>> F castByName(final Enum<?> e, final Class<F> fClass) {
    return F.valueOf(fClass, e.name());
}

使用示例:

Size size = castByName(Shape.UNKNOWN, Size.class);

2
感谢您的细节。 - Naman

9

您可以在Enum1中定义一个方法来返回相应的Enum2:

enum Enum1 {
    ONE {
        @Override
        public Enum2 toEnum2() {
            return Enum2.ALFA;
        }
    },
    TWO {
        @Override
        public Enum2 toEnum2() {
            return Enum2.BETA;
        }
    }
    ,
    THREE {
        @Override
        public Enum2 toEnum2() {
            return Enum2.GAMMA;
        }
    }
    ;

    public abstract Enum2 toEnum2();
}

enum Enum2 {
    ALFA, BETA, GAMMA;
}

或者说,更易读一些(在我看来):
enum Enum1 {
    ONE(Enum2.ALFA), 
    TWO(Enum2.BETA), 
    THREE(Enum2.GAMMA);

    private final Enum2 enum2;

    private Enum1(Enum2 enum2) {
        this.enum2 = enum2;
    }

    public Enum2 toEnum2() {
        return enum2;
    }
}

enum Enum2 {
    ALFA, BETA, GAMMA;
}

编辑:
如果需要保持两个枚举类解耦,可以创建一个包含从Enum1到Enum2的映射的Map(在第三个实用程序类中)。


6

不可能的。Enum1和Enum2是两种没有任何共同点的不同类型。


3
在Java中,枚举类型(Enums)的行为不像C或C#中的枚举类型。它们不是由某个常量数值支持的,而是完整的对象,并且有一些特殊的编译器技巧,使它们能够在switch语句等场景下工作。但即使像C那样,我认为试图从一个“枚举”类型直接进行类型转换到另一个“枚举”类型也是设计不良的,因为它们从程序角度来看代表的不同。 - StriplingWarrior

6

虽然这个票已经很久之前就激活了,但我还要添加另一种可能性:

您也可以创建一个地图,例如像这样:

HashMap<Enum1, Enum2> e1ToE2 = new HashMap<Enum1, Enum2>();
e1ToE2.put(Enum1.ONE, Enum2.FOUR);
e1ToE2.put(Enum1.TWO, Enum2.FIVE);

使用方法

Enum2 e2 = e1ToE2.get(Enum1.ONE);

(+) 无需再次检查您的元素顺序

(+) 易于阅读

(+) 快速

(-) 需要空间

如果我有错误,请纠正我 :)


4

由于它们是不同类的对象,所以您无法这样做。

您可以基于序数值或名称进行转换,但我会质疑任何需要执行此操作的程序的设计。


3
你不能在枚举类型中添加翻译;但你可以在枚举类型中创建一个静态方法,并加入翻译代码。但是,你必须明确实现规则的清晰思路。

我其实不太确定怎么做。 - Android-Droid
这不应该是一个静态方法,实例方法也可以(尽管对于更大的枚举来说维护起来会更麻烦)。@Bombastic:枚举类型是对象 enum Enum1 { ONE { public Enum2 toEnum2() { return Enum2.FOUR; } },... 你还应该为整个枚举类型添加一个抽象方法。 - user85421

2
无法进行强制转换,但您可以为 enum1 编写一个静态成员函数来将 enum2 转换为 enum1:
public static Enum1 fromEnum2(Enum2 enum2) {
    ...
}

顺便提一下,你可以为两个枚举类型的每个常量分配一个ID,这样可以简化实现。 这里有一个关于枚举类型的教程。

0

它可能对你没有帮助,但你可以拥有

public enum Enum1 implements MyInterface {...}
public enum Enum2 implements MyInterface {...}

我们没有足够的信息来帮助你完成操作。将一个枚举转换为另一个枚举是没有意义的。

0

你不能将一个枚举类型转换为另一个枚举类型,但是每个枚举类型都有保证的顺序,因此你可以轻松地将一个枚举类型翻译成另一个枚举类型


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接