【问题标题】:How to use Enum.valueOf from Scala?如何使用 Scala 中的 Enum.valueOf?
【发布时间】:2011-05-19 22:03:41
【问题描述】:
我需要从给定 Enum 的 Class 实例的字符串中获取 Java 枚举值。我尝试了如下代码,但出现“未绑定通配符类型”编译错误。似乎,我需要对存在类型做一些事情,forSome {} 或其他东西,但我不知道如何正确地做。
val paramClass = method.getParameterTypes()(0)
val value = paramClass match {
case _ if classOf[Enum[_]].isAssignableFrom(paramClass) => Enum.valueOf[_ <: Enum[_]](paramClass.asInstanceOf[Class[_ <: Enum[_]]], "MYENUM")
【问题讨论】:
标签:
java
scala
enums
existential-type
【解决方案1】:
嗯,艰难的一个。我有一个可行的解决方案,但我觉得它很难看。我会对任何更优雅的方法感兴趣!
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,并且永远不要尝试自己指定它(因为我们不应该知道它)——从而提取对Enum.valueOf的调用在另一种方法中,让编译器有机会绑定T <: Enum[T]。
正如我所说,我对这个解决方案不太满意,它看起来比应该的要复杂得多……
更新:我稍微简化了代码。