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

11

23

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!

Exodus answered 2/9, 2011 at 13:54 Comment(1)
What would you expect en2 to hold when you "cast" Enum1.ONE to it?Araiza
M
39

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()];
}
Mccormick answered 2/9, 2011 at 14:49 Comment(0)
W
22

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 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 an exception 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);
Wideman answered 10/11, 2016 at 16:36 Comment(1)
Appreciate the details.Inlay
G
9

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).

Gyrate answered 2/9, 2011 at 14:29 Comment(0)
B
6

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

Bencher answered 2/9, 2011 at 13:56 Comment(1)
+1: Enums in Java don't behave like Enums in C or C#. They're not backed by some constant numeric value. They're actually full-blown objects with some special compiler tricks to allow them to work in switch cases and such. But even if it were like C, I'd consider it bad design to try to do a straight-across cast from one enum type to another, based on what they're supposed to represent from a programming standpoint.Groundsel
E
6

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 :)

Euton answered 30/9, 2014 at 14:37 Comment(0)
M
4

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.

Mac answered 2/9, 2011 at 13:56 Comment(0)
S
3

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.

Salomie answered 2/9, 2011 at 13:57 Comment(2)
I'm not really sure how to do that actually.Exodus
it must not be a static method, an instance method would also do (agreed it's more work to maintain for bigger enums). @Bombastic: enums are objects enum Enum1 { ONE { public Enum2 toEnum2() { return Enum2.FOUR; } },... you should also add an abstract method to the whole enum.Gyrate
A
2

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.

Ancon answered 2/9, 2011 at 13:58 Comment(0)
A
0

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.

Addax answered 2/9, 2011 at 14:10 Comment(0)
R
0

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

Radiolarian answered 2/1, 2017 at 6:23 Comment(0)
T
0

If you need a default value:

Arrays.stream(Enum2.values())
      .filter(value -> value.name().equals(Enum1.ONE.name()))
      .findFirst()
      .orElse(Enum2.FOUR)
Tuberculate answered 28/2, 2023 at 10:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.