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!

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Android-Droid
  • 14,365
  • 41
  • 114
  • 185

11 Answers11

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()];
}
Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
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);
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
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).

user85421
  • 28,957
  • 10
  • 64
  • 87
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 :)

codewing
  • 674
  • 8
  • 25
6

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

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • 3
    +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. – StriplingWarrior Sep 02 '11 at 14:01
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.

parsifal
  • 1,507
  • 8
  • 7
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.

Raveline
  • 2,660
  • 1
  • 24
  • 28
  • I'm not really sure how to do that actually. – Android-Droid Sep 02 '11 at 14:07
  • 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. – user85421 Sep 02 '11 at 14:23
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.

alfa
  • 3,058
  • 3
  • 25
  • 36
0

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

T.Harini
  • 1
  • 2
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.

toto2
  • 5,306
  • 21
  • 24
0

If you need a default value:

Arrays.stream(Enum2.values())
      .filter(value -> value.name().equals(Enum1.ONE.name()))
      .findFirst()
      .orElse(Enum2.FOUR)
fab
  • 330
  • 3
  • 6