如何从Kotlin中的Int创建枚举?

时间:2018-11-28 16:24:51

标签: kotlin

我有这个enum

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

如何使用enum创建该Int的实例?

我试图做这样的事情:

val type = Types.valueOf(1)

我得到了错误:

  

整数文字不符合预期的字符串类型

8 个答案:

答案 0 :(得分:8)

如果仅使用整数值来维护顺序(需要访问正确的值),则不需要任何额外的代码。您可以使用内置值ordinal。序数表示值在枚举声明中的位置。

这里是一个例子:

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
}

您只需调用以下即可访问序数值:

Types.FOO.ordinal

要获取正确的枚举值,您只需调用:

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

Types.values()按声明顺序返回枚举值。

摘要:

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

如果整数值不匹配顺序(int_value!= enum.ordinal),或者您使用的是其他类型(string,float ...),那么您就需要迭代并比较自定义值,如前所述该线程。

答案 1 :(得分:5)

Enum#valueOf is based on name。这意味着要使用它,您需要使用valueof("FOO")valueof方法还采用了一个String,它解释了该错误。字符串不是整数。类型很重要。我之所以也提到它的原因是,所以您知道这不是您要寻找的方法。

如果要基于int值获取一个值,则需要定义自己的函数。您可以使用values()获取枚举中的值,在这种情况下,该值将返回Array<Types>。您可以使用firstOrNull作为一种安全的方法,如果您希望使用例外而不是null,则可以使用first

因此添加一个伴随对象(相对于枚举是静态的,因此可以在Types.getByValue(1234)上调用Types.COMPANION.getByValue(1234)(从Java来的Types.FOO.getByValue(1234))。

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

values()每次被调用时都会返回一个新数组,这意味着您应该在本地缓存该数组,以避免每次调用getByValue时都重新创建一个数组。如果在调用该方法时调用values(),则可能会反复创建它(取决于实际调用的次数),这会浪费内存。

如果您要执行此操作,则还可以扩展该功能并根据多个参数进行检查。这些类型的函数不仅限于一个参数。

该函数的命名完全取决于您。不必是getByValue

答案 2 :(得分:2)

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

您可能要为该范围添加安全检查并返回null。

答案 3 :(得分:0)

一种幼稚的方式可以是:

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

然后您可以使用

var bar = Types.valueOf(2)

答案 4 :(得分:0)

这实际上取决于您实际想要做什么。

  • 如果您需要特定的硬编码枚举值,则可以直接使用Types.FOO
  • 如果您是从代码中的其他位置动态接收值,则应尝试直接使用枚举类型,以便不必执行此类转换
  • 如果您正在从Web服务接收价值,则反序列化工具中应该有一些东西可以进行这种转换(例如Jackson的@JsonValue
  • 如果要基于其属性之一(例如此处的value属性)获取枚举值,那么恐怕您将必须实现自己的转换方法,如@Zoe所指出的那样。

实现此自定义转换的一种方法是使用转换方法添加一个伴随对象:

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

    companion object {
        private val types = values().associate { it.value to it }

        fun findByValue(value: Int) = types[value]
    }
}

Kotlin中的伴侣对象旨在包含属于该类但不与任何实例绑定的成员(例如Java的static成员)。 在那里实现该方法,您可以通过调用以下方法来访问值:

var bar = Types.findByValue(2)

答案 5 :(得分:0)

我会提前构建“反向”图。可能不是很大的改进,但是代码也不多。

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]!!
    }
}

编辑:根据@hotkey的建议,map ... toMap()更改为associate

答案 6 :(得分:0)

尝试一下...

companion object{
    fun FromInt(v:Int):Type{
        return  Type::class.java.constructors[0].newInstance(v) as Type
    }
}

答案 7 :(得分:0)

对于那些想要避免为每种类型声明fromInt(...)的人,请使用class EnumHelper private constructor() { companion object { inline fun <reified E : Enum<E>> fromInt(value: Int): E { return enumValues<E>().first { it.toString().toInt() == value } } } } ,这是一种方法:

Helper类:

enum class FancyEnum(val value: Int){
    First(0),
    Second(1);

    override fun toString(): String = value.toString()
}

枚举示例:

...
fun getPosition(): FancyEnum{
    return EnumHelper.fromInt(aGoodIntValue)
}
...

用法:

...
val fancy = EnumHelper.fromInt<FancyEnum>(aGoodIntValue)
val fancyTwo : FancyEnum = EnumHelper.fromInt(aGoodIntValue)
...

{{ foo[:1]|lower ~ foo[1:] }}
相关问题