How do I create an enum from a Int in Kotlin?

2020-07-02 09:15发布

I have this enum:

enum class Types(val value: Int) {
    FOO(1)
    BAR(2)
    FOO_BAR(3)
}

How do I create an instance of that enum using an Int?

I tried doing something like this:

val type = Types.valueOf(1)

And I get the error:

Integer literal does not conform to the expected type String

标签: kotlin
7条回答
该账号已被封号
2楼-- · 2020-07-02 09:50

Enum#valueOf is based on name. Which means in order to use that, you'd need to use valueof("FOO"). The valueof method also takes a String, which explains the error. A String isn't an Int; types matter. The reason I mentioned what it does too, is so you know this isn't the method you're looking for.

If you want to grab one based on an int value, you need to define your own function to do so. You can get the values in an enum using values(), which returns an Array<Types> in this case. You can use firstOrNull as a safe approach, or first if you prefer an exception over null.

So add a companion object (which are static relative to the enum, so you can call Types.getByValue(1234) (Types.COMPANION.getByValue(1234) from Java) over Types.FOO.getByValue(1234).

companion object {
    private val values = values();
    fun getByValue(value: Int) = values.firstOrNull { it.value == value }
}

values() returns a new Array every time it's called, which means you should cache it locally to avoid re-creating one every single time you call getByValue. If you call values() when the method is called, you risk re-creating it repeatedly (depending on how many times you actually call it though), which is a waste of memory.

The function could also be expanded and check based on multiple parameters, if that's something you want to do. These types of functions aren't limited to one argument.

Naming of the function is entirely up to you though. It doesn't have to be getByValue.

查看更多
男人必须洒脱
3楼-- · 2020-07-02 09:55

If you are using integer value only to maintain order, which you need to access correct value, then you don't need any extra code. You can use build in value ordinal. Ordinal represents position of value in enum declaration.

Here is an example:

enum class Types {
    FOO,               //Types.FOO.ordinal == 0 also position == 0
    BAR,               //Types.BAR.ordinal == 1 also position == 1
    FOO_BAR            //Types.FOO_BAR.ordinal == 2 also position == 2
}

You can access ordinal value simply calling:

Types.FOO.ordinal

To get correct value of enum you can simply call:

Types.values()[0]      //Returns FOO
Types.values()[1]      //Returns BAR
Types.values()[2]      //Returns FOO_BAR

Types.values() returns enum values in order accordingly to declaration.

Summary:

Types.values(Types.FOO.ordinal) == Types.FOO //This is true

If integer values don't match order (int_value != enum.ordinal) or you are using different type (string, float...), than you need to iterate and compare your custom values as it was already mentioned in this thread.

查看更多
迷人小祖宗
4楼-- · 2020-07-02 09:58

I would build the 'reverse' map ahead of time. Probably not a big improvement, but also not much code.

enum class Test(val value: Int) {
    A(1),
    B(2);

    companion object {
        val reverseValues: Map<Int, Test> = values().associate { it.value to it }
        fun valueFrom(i: Int): Test = reverseValues[i]!!
    }
}

Edit: map...toMap() changed to associate per @hotkey's suggestion.

查看更多
Viruses.
5楼-- · 2020-07-02 10:00

A naive way can be:

enum class Types(val value: Int) {
    FOO(1),
    BAR(2),
    FOO_BAR(3);

    companion object {
        fun valueOf(value: Int) = Types.values().find { it.value == value }
    }
}

Then you can use

var bar = Types.valueOf(2)
查看更多
狗以群分
6楼-- · 2020-07-02 10:02

try this...

companion object{
    fun FromInt(v:Int):Type{
        return  Type::class.java.constructors[0].newInstance(v) as Type
    }
}
查看更多
一夜七次
7楼-- · 2020-07-02 10:04
enum class Types(val value: Int) {
    FOO(1),
    BAR(2),
    FOO_BAR(3);

    companion object {
        fun fromInt(value: Int) = Types.values().first { it.value == value }
    }
}

You may want to add a safety check for the range and return null.

查看更多
登录 后发表回答