如何使用Scala的Enum.valueOf?

nau*_*nau 5 java enums scala existential-type

我需要从给定Enum的Class实例的字符串中获取Java枚举值.我尝试了下面的代码,但我得到"未绑定的通配符类型"编译错误.似乎,我需要对存在类型做一些事情,对于某些事情,但是我无法理解如何做到这一点.

val paramClass = method.getParameterTypes()(0)
val value = paramClass match {
  case _ if classOf[Enum[_]].isAssignableFrom(paramClass) => Enum.valueOf[_ <: Enum[_]](paramClass.asInstanceOf[Class[_ <: Enum[_]]], "MYENUM")
Run Code Online (Sandbox Code Playgroud)

Jea*_*let 7

嗯,艰难的一个.我有一个有效的解决方案,但我发现它很难看.我会对任何更优雅的方法感兴趣!

def enumValueOf[T <: Enum[T]](cls: Class[_], stringValue: String): Enum[_] =
  Enum.valueOf(cls.asInstanceOf[Class[T]], stringValue).asInstanceOf[Enum[_]]

val value = paramClass match {
  case _ if classOf[Enum[_]].isAssignableFrom(paramClass) => enumValueOf(paramClass, "MYENUM")
  case _ => // other cases
}
Run Code Online (Sandbox Code Playgroud)

认为我们需要这种复杂性的原因......

我们需要编译器相信Class[_]我们实际上是一个Class[T <: Enum[T]](当然,这是一个初步的测试,这确实是一个Java枚举 - 就像你的代码中所做的那样 - 是必需的).所以我们cls转向Class[T],T编译器推断出来的地方<: Enum[T].但是编译器仍然需要找到合适的T,默认为Nothing这里.因此,就编译器而言,cls.asInstanceOf[Class[T]]是一个Class[Nothing].这暂时没问题,因为它可以用来调用Enum.valueOf- 问题是推断的返回类型valueOf当然Nothing也是如此.这里我们遇到了一个问题,因为当我们尝试实际使用类型的实例时,编译器会插入一个异常Nothing.所以,我们最终将返回值valueOf转换为Enum[_].

然后诀窍是始终让编译器推断出类型参数,enumValueOf并且永远不要尝试自己指定它(因为我们不应该知道它) - 从而Enum.valueOf在另一个方法中提取调用,给编译器一个机会绑定一个T <: Enum[T].

正如我所说,我对这个解决方案不太满意,看起来比应该更复杂......

更新:我稍微简化了代码.