Scala转换为变量类型
我有以下代码将 value 转换为 default 类型:
I have the following code to cast value to the type of 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行,但是在函数调用期间未引发任何异常。
Question is: why the println is displayed? The cast should fail. I tried to try / catch the 3 lines but no exception are raised during the function call.
由于类型擦除,它是不可能实际上实现值。{as / is} InstanceOf [T]
其中, T
是类型参数。 Scala的设计师认为它仍然应该编译,但是 value.asInstanceOf [T]
实际上是一个空操作(就像等效的(T)值
(在Java中为/ code>),而 value.isInstanceOf [T]
始终返回 true
(在Java中, value instanceOf T
是编译器错误)。 (由于它从不执行您想要的操作,因此我强烈希望看到警告,至少对于 isInstanceOf
而言。)
Because of type erasure, it's impossible to actually implement value.{as/is}InstanceOf[T]
where T
is a type parameter. Scala's designers decided it should still compile, but value.asInstanceOf[T]
is actually a no-op (just like the equivalent (T) value
in Java), while value.isInstanceOf[T]
always returns true
(in Java, value instanceOf T
is a compiler error). (Since it never does what you want, I'd strongly like to see a warning instead, at least for isInstanceOf
.)
但是Scala允许使用 ClassTag
:
But Scala allows to do what you want using ClassTag
:
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
通常返回相同的类 T
表示但并非总是如此,因此其静态返回类型为o是 Class [_]
和 cast
返回 Any
) 。
(You still need asInstanceOf[T]
because tag.runtimeClass
usually returns the same class T
represents but not always, so its static return type has to be Class[_]
and cast
returns Any
).
但是,模式匹配:T
可以处理 ClassTag
已自动处理拳击,因此
However, pattern-matching : T
handles presence of a ClassTag
automatically and already handles boxing, so
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
}
是更好的方法。