繁体   English   中英

Scala强制转换为变量类型

[英]Scala cast to a variable type

我有以下代码将转换为默认类型:

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行,但在函数调用期间没有异常。

由于类型擦除, 实际上不可能实现value.{as/is}InstanceOf[T]其中T是类型参数。 Scala的设计者认为它仍然应该编译,但value.asInstanceOf[T]实际上是一个无操作(就像Java中的等效(T) value ),而value.isInstanceOf[T]总是返回true (在Java中, value instanceOf T是编译器错误)。 (因为它永远不会做你想要的,我非常希望看到一个警告,至少对于isInstanceOf 。)

但是Scala允许使用ClassTag做你想做的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代表但不总是,所以它的静态返回类型必须是Class[_]并且cast返回Any )。

但是,模式匹配: T自动处理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
}

这是更好的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM