Cast Int to enum in Java

JavaCastingEnumsOrdinal

Java Problem Overview


What is the correct way to cast an Int to an enum in Java given the following enum?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


MyEnum enumValue = (MyEnum) x; //Doesn't work???

Java Solutions


Solution 1 - Java

Try MyEnum.values()[x] where x must be 0 or 1, i.e. a valid ordinal for that enum.

Note that in Java enums actually are classes (and enum values thus are objects) and thus you can't cast an int or even Integer to an enum.

Solution 2 - Java

MyEnum.values()[x] is an expensive operation. If the performance is a concern, you may want to do something like this:

public enum MyEnum {
    EnumValue1,
    EnumValue2;

    public static MyEnum fromInteger(int x) {
    	switch(x) {
    	case 0:
    		return EnumValue1;
    	case 1:
    		return EnumValue2;
    	}
    	return null;
    }
}

Solution 3 - Java

If you want to give your integer values, you can use a structure like below

public enum A
{
        B(0),
        C(10),
        None(11);
        int id;
        private A(int i){id = i;}
   
        public int GetID(){return id;}
    	public boolean IsEmpty(){return this.equals(A.None);}
    	public boolean Compare(int i){return id == i;}
    	public static A GetValue(int _id)
    	{
    		A[] As = A.values();
    		for(int i = 0; i < As.length; i++)
    		{
    			if(As[i].Compare(_id))
    				return As[i];
    		}
    		return A.None;
    	}
}

Solution 4 - Java

You can try like this.
Create Class with element id.

      public Enum MyEnum {
        THIS(5),
        THAT(16),
        THE_OTHER(35);
    
        private int id; // Could be other data type besides int
        private MyEnum(int id) {
            this.id = id;
        }
    
        public static MyEnum fromId(int id) {
                for (MyEnum type : values()) {
                    if (type.getId() == id) {
                        return type;
                    }
                }
                return null;
            }
      }

Now Fetch this Enum using id as int.

MyEnum myEnum = MyEnum.fromId(5);

Solution 5 - Java

I cache the values and create a simple static access method:

public static enum EnumAttributeType {
	ENUM_1,
	ENUM_2;
	private static EnumAttributeType[] values = null;
	public static EnumAttributeType fromInt(int i) {
		if(EnumAttributeType.values == null) {
			EnumAttributeType.values = EnumAttributeType.values();
		}
		return EnumAttributeType.values[i];
	}
}

Solution 6 - Java

Java enums don't have the same kind of enum-to-int mapping that they do in C++.

That said, all enums have a values method that returns an array of possible enum values, so

MyEnum enumValue = MyEnum.values()[x];

should work. It's a little nasty and it might be better to not try and convert from ints to Enums (or vice versa) if possible.

Solution 7 - Java

This not something that is usually done, so I would reconsider. But having said that, the fundamental operations are: int --> enum using EnumType.values()[intNum], and enum --> int using enumInst.ordinal().

However, since any implementation of values() has no choice but to give you a copy of the array (java arrays are never read-only), you would be better served using an EnumMap to cache the enum --> int mapping.

Solution 8 - Java

Use MyEnum enumValue = MyEnum.values()[x];

Solution 9 - Java

Here's the solution I plan to go with. Not only does this work with non-sequential integers, but it should work with any other data type you may want to use as the underlying id for your enum values.

public Enum MyEnum {
	THIS(5),
	THAT(16),
	THE_OTHER(35);
	
	private int id; // Could be other data type besides int
	private MyEnum(int id) {
		this.id = id;
	}
	
	public int getId() {
		return this.id;
	}
	
	public static Map<Integer, MyEnum> buildMap() {
		Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
		MyEnum[] values = MyEnum.values();
		for (MyEnum value : values) {
			map.put(value.getId(), value);
		}
		
		return map;
	}
}

I only need to convert id's to enums at specific times (when loading data from a file), so there's no reason for me to keep the Map in memory at all times. If you do need the map to be accessible at all times, you can always cache it as a static member of your Enum class.

Solution 10 - Java

In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:

public enum MyEnum {
    OPTION_1(-66),
    OPTION_2(32);

    private int value;
    private MyEnum(final int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    private static ImmutableMap<Integer, MyEnum> reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(MyEnum.values())), MyEnum::getValue);

    public static MyEnum fromInt(final int id) {
        return reverseLookup.getOrDefault(id, OPTION_1);
    }
}

With the default you can use null, you can throw IllegalArgumentException or your fromInt could return an Optional, whatever behavior you prefer.

Solution 11 - Java

Based on @ChadBefus 's answer and @shmosel comment, I'd recommend using this. (Efficient lookup, and works on pure java >= 8)

import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import java.util.Arrays;

public enum MyEnum {
    OPTION_1(-66),
    OPTION_2(32);

    private int value;
    private MyEnum(final int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    private static Map<Integer, MyEnum> reverseLookup =
        Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));

    public static MyEnum fromInt(final int id) {
        return reverseLookup.getOrDefault(id, OPTION_1);
    }
    public static void main(String[] args) {
        System.out.println(fromInt(-66).toString());
    }
}

Solution 12 - Java

You can iterate over values() of enum and compare integer value of enum with given id like below:

public enum  TestEnum {
    None(0),
    Value1(1),
    Value2(2),
    Value3(3),
    Value4(4),
    Value5(5);

	private final int value;
	private TestEnum(int value) {
		this.value = value;
	}

	public int getValue() {
		return value;
	}

	public static TestEnum  getEnum(int value){
		for (TestEnum e:TestEnum.values()) {
			if(e.getValue() == value)
				return e;
		}
		return TestEnum.None;//For values out of enum scope
	}
}

And use just like this:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
I hope this helps ;)

Solution 13 - Java

Wrote this implementation. It allows for missing values, negative values and keeps code consistent. The map is cached as well. Uses an interface and needs Java 8.

Enum

public enum Command implements OrdinalEnum{
	PRINT_FOO(-7),
	PRINT_BAR(6),
	PRINT_BAZ(4);
	
	private int val;
	private Command(int val){
		this.val = val;
	}
	
	public int getVal(){
		return val;
	}
	
	private static Map<Integer, Command> map = OrdinalEnum.getValues(Command.class);
	public static Command from(int i){
		return map.get(i);
	}
}

Interface

public interface OrdinalEnum{
	public int getVal();
	
	@SuppressWarnings("unchecked")
	static <E extends Enum<E>> Map<Integer, E> getValues(Class<E> clzz){
		Map<Integer, E> m = new HashMap<>();
		for(Enum<E> e : EnumSet.allOf(clzz))
			m.put(((OrdinalEnum)e).getVal(), (E)e);
		
		return m;
	}
}

Solution 14 - Java

A good option is to avoid conversion from int to enum: for example, if you need the maximal value, you may compare x.ordinal() to y.ordinal() and return x or y correspondingly. (You may need to re-order you values to make such comparison meaningful.)

If that is not possible, I would store MyEnum.values() into a static array.

Solution 15 - Java

This is the same answer as the doctors but it shows how to eliminate the problem with mutable arrays. If you use this kind of approach because of branch prediction first if will have very little to zero effect and whole code only calls mutable array values() function only once. As both variables are static they will not consume n * memory for every usage of this enumeration too.

private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;

public static RFMsgType GetMsgTypeFromValue(int MessageID) {
	if (arrayCreated == false) {
		ArrayOfValues = RFMsgType.values();
	}

	for (int i = 0; i < ArrayOfValues.length; i++) {
		if (ArrayOfValues[i].MessageIDValue == MessageID) {
			return ArrayOfValues[i];
		}
	}
	return RFMsgType.UNKNOWN;
}

Solution 16 - Java

enum MyEnum {
    A(0),
    B(1);
    private final int value;
    private MyEnum(int val) {this.value = value;}
    private static final MyEnum[] values = MyEnum.values();//cache for optimization
    public static final getMyEnum(int value) { 
        try {
            return values[value];//OOB might get triggered
        } catch (ArrayOutOfBoundsException e) {
        } finally {
            return myDefaultEnumValue;
        }
    }
}

Solution 17 - Java

In Kotlin:

enum class Status(val id: Int) {
    NEW(0), VISIT(1), IN_WORK(2), FINISHED(3), CANCELLED(4), DUMMY(5);

    companion object {
        private val statuses = Status.values().associateBy(Status::id)

        fun getStatus(id: Int): Status? = statuses[id]
    }
}

Usage:

val status = Status.getStatus(1)!!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMaxim GershkovichView Question on Stackoverflow
Solution 1 - JavaThomasView Answer on Stackoverflow
Solution 2 - JavaLorenzo PolidoriView Answer on Stackoverflow
Solution 3 - JavaDoctorView Answer on Stackoverflow
Solution 4 - JavaPiyush GhediyaView Answer on Stackoverflow
Solution 5 - JavaossysView Answer on Stackoverflow
Solution 6 - JavaCameron SkinnerView Answer on Stackoverflow
Solution 7 - JavaDilum RanatungaView Answer on Stackoverflow
Solution 8 - Javaw.donahueView Answer on Stackoverflow
Solution 9 - JavajkindwallView Answer on Stackoverflow
Solution 10 - JavaChad BefusView Answer on Stackoverflow
Solution 11 - JavaYuki InoueView Answer on Stackoverflow
Solution 12 - JavaYashar AliabbasiView Answer on Stackoverflow
Solution 13 - JavaGerrit BrinkView Answer on Stackoverflow
Solution 14 - Java18446744073709551615View Answer on Stackoverflow
Solution 15 - JavaAli AkdurakView Answer on Stackoverflow
Solution 16 - JavaZosoView Answer on Stackoverflow
Solution 17 - JavaCoolMindView Answer on Stackoverflow