I need to get a Java enum value from a string given Enum’s Class instance. I tried code like below, but I’m getting “unbound wildcard type” compilation error. Seems, I need to do something with existential types, forSome {} or something, but I can’t get how to do it right.
val paramClass = method.getParameterTypes()(0)
val value = paramClass match {
case _ if classOf[Enum[_]].isAssignableFrom(paramClass) => Enum.valueOf[_ <: Enum[_]](paramClass.asInstanceOf[Class[_ <: Enum[_]]], "MYENUM")
Hmm, tough one. I have a working solution, but I find it ugly. I’ll be interested in any more elegant approach!
The reason why I think we need this complexity…
We need the compiler to believe that the
Class[_]we have is actually aClass[T <: Enum[T]](so of course, a preliminary test that this is indeed a Java enum — as done in your code — is needed). So we castclstoClass[T], whereTwas inferred by the compiler to be<: Enum[T]. But the compiler still has to find a suitableT, and defaults toNothinghere. So, as far as the compiler is concerned,cls.asInstanceOf[Class[T]]is aClass[Nothing]. This is temporarily OK since it can be used to callEnum.valueOf— the problem is that the inferred return type ofvalueOfis then, naturally,Nothingas well. And here we have a problem, because the compiler will insert an exception when we try to actually use an instance of typeNothing. So, we finally cast the return value ofvalueOfto anEnum[_].The trick is then to always let the compiler infer the type argument to
enumValueOfand never try to specify it ourselves (since we’re not supposed to know it anyway) — and thus to extract the call toEnum.valueOfin another method, giving the compiler a chance to bind aT <: Enum[T].As I said, I’m not very happy with this solution, which looks way more complicated than it should be…
Update: I’ve simplified the code slightly.