如何使用Scala的Enum.valueOf?

时间:2011-05-19 08:58:19

标签: java scala enums 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")

1 个答案:

答案 0 :(得分: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
}

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

我们需要编译器相信我们所拥有的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的类型参数,并且永远不会尝试自己指定它(因为我们不应该知道它) - 从而提取对{的调用{1}}在另一种方法中,让编译器有机会绑定Enum.valueOf

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

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