2011-05-19 56 views
4

我需要從給定枚舉類實例的字符串中獲取Java枚舉值。我嘗試下面的代碼,但我得到「未綁定通配符類型」編譯錯誤。看起來,我需要用存在類型做些事情,forSome {}或其他東西,但是我不知道怎麼做纔對。如何從Scala使用Enum.valueOf?

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

回答

6

嗯,艱難的一個。我有一個工作解決方案,但我覺得它很難看。我會對任何更優雅的方法感興趣!

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]的機會。

正如我所說的,我不是很滿意這個解決方案,它看起來方式複雜得多,它應該是...

更新:我稍微簡化了代碼。