https://kotlinlang.org logo
Title
d

David R.

02/27/2019, 2:31 PM
Is there a way in Kotlin to create an empty EnumSet from a reflected enum Class? It seems like I can do it with Java, but not with Kotlin based on the enum type constraints and inference (and if I take Java code and paste it into Kotlin and have IntelliJ do the auto convert, it fails)
m

Marc Knaup

02/27/2019, 3:06 PM
You can make use of generic type erasure, like this:
import java.util.EnumSet
import kotlin.reflect.KClass


private enum class Dummy


@Suppress("UNCHECKED_CAST")
fun <E: Enum<E>> emptyEnumSet(clazz: KClass<E>) =
	EnumSet.noneOf(clazz.java as Class<Dummy>) as EnumSet<E>


@JvmName("emptyEnumSetOfUnspecificClass")
@Suppress("UNCHECKED_CAST")
fun emptyEnumSet(clazz: KClass<out Enum<*>>) =
	EnumSet.noneOf(clazz.java as Class<Dummy>) as EnumSet<*>


@Suppress("UNCHECKED_CAST")
inline fun <reified E: Enum<E>> emptyEnumSet() =
	EnumSet.noneOf(E::class.java as Class<Dummy>) as EnumSet<E>


enum class MyEnum {
	a,b
}


fun main() {
	val unspecificEnumClass = MyEnum::class as KClass<out Enum<*>>
	val emptySet1 = emptyEnumSet(MyEnum::class)
	val emptySet2 = emptyEnumSet<MyEnum>()
	val emptySet3 = emptyEnumSet(unspecificEnumClass)

	println(emptySet1)
	println(emptySet2)
	println(emptySet3)
}
d

David R.

02/27/2019, 3:32 PM
Thanks. The above didn't exactly work for my needs (because I'm dealing with a Class<?> coming from Java so type inference still wasn't happy, but the idea to create an empty enum class and then cast to that does seem to work, which I hadn't thought of before.
m

Marc Knaup

02/27/2019, 3:34 PM
You can use the method above, again with a little cast:
val veryUnspecificClass: Class<*> = unspecificEnumClass.java
val emptySet4 = emptyEnumSet(veryUnspecificClass.kotlin as KClass<out Enum<*>>)
Class<?>
is quite unsafe, hence a cast needed.
Class<out Enum<*>>
would be better 🙂
d

David R.

02/27/2019, 3:38 PM
Yeah, I'm dealing with reflection, so I've already verified the class is an enum, so for my case it's safe
👍 1
If all I want is an an empty enum set instance, is there any reason I can't just declare the empty enum (Dummy in the above example) and then just do EnumSet.noneOf(Dummy::class.java)
m

Marc Knaup

02/27/2019, 3:42 PM
You can, I just generalized your use-case with some functions and added different examples. But you have to cast the resulting
EnumSet<Dummy>
to
EnumSet<*>
🙂
d

David R.

02/27/2019, 3:43 PM
Cool. Yeah, in my case the value I'm assuming to is already Any?, so for me the cast isn't necessary
👍 1
In case anyone is wondering the use case here where everything seems so loosely typed, it's for our fork of the kotlin jackson module that allows us to automatically map null EnumSets to empty on deserialization (similarly, we have logic to map null lists/maps to empty lists/maps)
m

Marc Knaup

02/27/2019, 3:49 PM
So could also be interesting for my own Kotlin JSON library 😄 I've never ever used
EnumSet
though 😮 Maybe I should add a Kotlin-version of it 🙂