How to cast a value from one enum to another in Java?

心不动则不痛 提交于 2021-01-21 02:31:26

问题


How can I cast a value from Enum1 to Enum 2 in Java? Here is an example of what I'm trying to do :

public enum Enum1 {
  ONE,
  TWO,
  THREE;
}

public enum Enum2 {
  FOUR,
  FIVE,
  SIX;
}

So I want to do something like this:

Enum2 en2 = (Enum2)ONE;

Is it possible and how can I do that?

Thanks in advance!


回答1:


You cannot cast from one enum to another, however each enum has guaranteed order, and you can easily translate one enum to another (preserving order). For example:

enum E1 {
    ONE, TWO, THREE,
}

enum E2 {
    ALPHA, BETA, GAMMA,
}

we can translate E1.TWO to/from E2.BETA by:

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

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



回答2:


The answer depends on what the "casting" should do...

Casting by ordinal position

In the provided example, there is no commonality between the two sets of enum values so I'm assuming the intention was to translate by ordinal position so Enum1.ONE => Enum2.FOUR, Enum1.TWO => Enum2.FIVE and Enum1.THREE => Enum2.SIX. This can be done as follows:

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

A natural follow-on question is how this can be extended to a generic function that does the same for any two enum types. Not for the faint hearted but this does the job - it requires the Google Guava library:

public <F extends Enum<F>> F castByOrdinal(Enum<?> e, Class<F> fClass) {
    return Iterators.get(EnumSet.allOf(fClass).iterator(), e.ordinal());
}

If the Guava isn't being used, it can be done manually in a few more lines of code:

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 exception if preferred e.g. IndexOutOfBoundsException
        }
        fValue = iter.next();
        count++;
    }

    return fValue;
}

Example usage:

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

Casting by shared enum value names

There is another possible way of casting between enums that share some of the same value names.

E.g:

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

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

The casting will only work for common values (i.e. UNKNOWN and NOT_APPLICABLE above) and can be done as follows:

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

This will throw an IllegalArgumentException if the value name does not exist in the target enum. The generic method for this casting is a bit simpler:

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

Example usage:

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



回答3:


You can define a method in Enum1 to return the corresponding 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;
}

or, a bit more readable (IMO):

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

EDIT:
if you need to maintain the 2 enums decoupled, create a map containing the mapping from Enum1 to Enum2 (in a 3rd utility class).




回答4:


It's not possible. Enum1 and Enum2 are different types with nothing in common.




回答5:


You can't do that, because they're objects of different classes.

You could convert from one to the other based on ordinal value or name, but I'd question the design of any program that needed to do that.




回答6:


You can't ; but you can create a static method in your enums, with a translation code. But you must have a clear idea of the rules you want to implement.




回答7:


Even though this ticket was active quite a while ago I'm adding another possibility:

You could also create a Map e.g. like this:

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

usage

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

(+) you dont have to double check the order of your elements

(+) easy to read

(+) fast

(-) requires space

Correct me if I'm wrong :)




回答8:


A cast operation is not possible, but you can write a static member function for enum1 that casts enum2 to enum1:

public static Enum1 fromEnum2(Enum2 enum2) {
    ...
}

By the way, you can assign an ID to every constant of both enums which simplifies the implementation.

Here is a tutorial on enums.




回答9:


It probably won't help you, but you can have

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

We don't have enough information about what you are trying to do to help you. It makes no sense as it is to cast an enum to another enum.




回答10:


You cannot cast from one enum to another, however each enum has guaranteed order, and you can easily translate one enum to another




回答11:


You can do this by using simple way:

 public enum number{one,two};
        public enum number1{one,two};
        public void  castTonumber1(number number){

            number1 num1 = number1.valueOf(number.one.toString());
           System.out.println( "value of number 1 is " + num1);

        }*


来源:https://stackoverflow.com/questions/7284472/how-to-cast-a-value-from-one-enum-to-another-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!