我有以下代码要投射value的类型default:
def fct[T](value: Any, default: T): T = {
val result = value.asInstanceOf[T]
println(result, result.getClass.getName, result.isInstanceOf[T])
result
}
val res = fct("foo", 42)
其结果是:
(foo,java.lang.String,true)
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Test.sc2.tmp)
at #worksheet#.res$lzycompute(Test.sc2.tmp:7)
at #worksheet#.res(Test.sc2.tmp:7)
at #worksheet#.#worksheet#(Test.sc2.tmp:7)
问题是:为什么会显示println?演员阵容应该会失败。我尝试尝试/捕获这 3 行,但在函数调用期间没有引发异常。
由于类型擦除,不可能actually实施value.{as/is}InstanceOf[T]
where T
是一个类型参数。 Scala 的设计者决定它仍然应该编译,但是value.asInstanceOf[T]
实际上是一个无操作(就像等效的(T) value
在Java中),同时value.isInstanceOf[T]
总是返回true
(在爪哇语中,value instanceOf T
是编译器错误)。 (因为它永远不会做你想要的事情,所以我强烈希望看到一个警告,至少对于isInstanceOf
.)
但 Scala 允许使用做你想做的事ClassTag http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html:
import scala.reflect.ClassTag
def fct[T](value: Any, default: T)(implicit tag: ClassTag[T]): T = {
val result = (tag match {
case ClassTag.Int => value.asInstanceOf[Int]
... same for other primitives
case _ => tag.runtimeClass.cast(value)
}).asInstanceOf[T]
println(result, result.getClass.getName, tag.runtimeClass.isInstance(result))
result
}
(你还需要asInstanceOf[T]
因为tag.runtimeClass
usually返回相同的类T
代表但不总是,所以它的静态返回类型必须是Class[_]
and cast
回报Any
).
然而,模式匹配: T
处理 a 的存在ClassTag
自动并且已经处理拳击,所以
def fct[T](value: Any, default: T)(implicit tag: ClassTag[T]): T = value match {
case result: T => result
case _ => default // or whatever you want to do if value is not a T
}
是更好的方法来做到这一点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)