Scala 转换为变量类型

2024-07-03

我有以下代码要投射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(使用前将#替换为@)

Scala 转换为变量类型 的相关文章

随机推荐