ClassTag.runtimeClass.isInstance 不适用于 AnyVal
ClassTag.runtimeClass.isInstance does not work for AnyVal
使用 scala ClassTags 我发现 classTag.runtimeClass.isInstance 在与 AnyVal 对象一起使用时无法正常工作。这是一个片段,您可以在其中进行测试。有什么想法可以让 AnyVal 对象工作吗?
import scala.reflect.ClassTag
import scala.reflect.runtime.{universe => ru}
object Test {
def extractField[U: ru.TypeTag](json: Map[String, Any], field: String)(implicit classTag: ClassTag[U]): Option[U] = {
json.get(field) match {
case Some(value) =>
if(classTag.runtimeClass.isInstance(value))
Some(value.asInstanceOf[U])
else {
None
}
case _ =>
None
}
}
val map: Map[String,Any] = Map("k1" -> 2.0, "k2" -> "v")
extractField[Double](map,"k1") // RETURNS NONE
extractField[String](map,"k2") // RETURNS Some("v")
}
顺便说一句,我正在使用 Scala 2.10
下面是显示相同问题的更简单的代码:
val c = classTag[Double].runtimeClass
println(c) // double
println(c == classOf[Double]) // true
println(c.isInstance(0.0)) // false
isInstance
取 Object
。 classOf[Double]
代表JVM原语double
的"class"(和classTag[Double].runtimeClass
一样)。由于对象不能是原始对象,因此 classOf[Double].isInstance(something)
将始终为 false。
Map[String, Any]
实际上并不包含 AnyVal
,而只是对象;当你写
val map: Map[String,Any] = Map("k1" -> 2.0, "k2" -> "v")
2.0
自动装箱到 java.lang.Double
,因此您的代码正确地告诉您此键下没有 Double
。但是你可以写一个简单的辅助函数(我以为它在标准库的某个地方,但不记得在哪里):
private val boxedClasses =
Map[Class[_], Class[_]](classOf[Double] -> classOf[java.lang.Double], ...) // the rest of AnyVal classes
def boxed(c: Class[_]) = boxedClasses.getOrElse(c, c)
然后在 case Some(value)
:
if(boxed(classTag.runtimeClass).isInstance(value))
Some(value.asInstanceOf[U])
当然它无法在你的地图中分辨出Double
和java.lang.Double
之间的区别,因为这种区别不存在(编译时除外)。
使用 scala ClassTags 我发现 classTag.runtimeClass.isInstance 在与 AnyVal 对象一起使用时无法正常工作。这是一个片段,您可以在其中进行测试。有什么想法可以让 AnyVal 对象工作吗?
import scala.reflect.ClassTag
import scala.reflect.runtime.{universe => ru}
object Test {
def extractField[U: ru.TypeTag](json: Map[String, Any], field: String)(implicit classTag: ClassTag[U]): Option[U] = {
json.get(field) match {
case Some(value) =>
if(classTag.runtimeClass.isInstance(value))
Some(value.asInstanceOf[U])
else {
None
}
case _ =>
None
}
}
val map: Map[String,Any] = Map("k1" -> 2.0, "k2" -> "v")
extractField[Double](map,"k1") // RETURNS NONE
extractField[String](map,"k2") // RETURNS Some("v")
}
顺便说一句,我正在使用 Scala 2.10
下面是显示相同问题的更简单的代码:
val c = classTag[Double].runtimeClass
println(c) // double
println(c == classOf[Double]) // true
println(c.isInstance(0.0)) // false
isInstance
取 Object
。 classOf[Double]
代表JVM原语double
的"class"(和classTag[Double].runtimeClass
一样)。由于对象不能是原始对象,因此 classOf[Double].isInstance(something)
将始终为 false。
Map[String, Any]
实际上并不包含 AnyVal
,而只是对象;当你写
val map: Map[String,Any] = Map("k1" -> 2.0, "k2" -> "v")
2.0
自动装箱到 java.lang.Double
,因此您的代码正确地告诉您此键下没有 Double
。但是你可以写一个简单的辅助函数(我以为它在标准库的某个地方,但不记得在哪里):
private val boxedClasses =
Map[Class[_], Class[_]](classOf[Double] -> classOf[java.lang.Double], ...) // the rest of AnyVal classes
def boxed(c: Class[_]) = boxedClasses.getOrElse(c, c)
然后在 case Some(value)
:
if(boxed(classTag.runtimeClass).isInstance(value))
Some(value.asInstanceOf[U])
当然它无法在你的地图中分辨出Double
和java.lang.Double
之间的区别,因为这种区别不存在(编译时除外)。