[英]Scala asInstanceOf generic type does not fail in Try
Trying to cast a String
to a Double
obviously should fail: 尝试将
String
转换为Double
显然会失败:
scala> Try("abc".asInstanceOf[Double])
res11: scala.util.Try[Double] = Failure(java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double)
However, if I define the above as a function: 但是,如果我将以上定义为函数:
scala> def convertAsTypeOf[T](anyValue: Any): Try[T] = Try(anyValue.asInstanceOf[T])
convertAsTypeOf: [T](anyValue: Any)scala.util.Try[T]
Strangely it returns Success when I try to cast a String
to a Double
: 奇怪的是,当我尝试将
String
转换为Double
时,它返回Success:
scala> convertAsTypeOf[Double]("abc")
res10: scala.util.Try[Double] = Success(abc)
If I try to get the value out of Success, I get the following exception: 如果我试图从成功中获取价值,则会出现以下异常:
scala> convertAsTypeOf[Double]("abc").get
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
at scala.runtime.BoxesRunTime.unboxToDouble(BoxesRunTime.java:119)
Why does this happen? 为什么会这样? Is there any way to fix this and make
asInstanceOf[T]
when it's in a generic function? 在通用函数中,有什么方法可以解决这个问题并使其成为
asInstanceOf[T]
?
Because of type erasure, the type T
is unknown at runtime, so asInstanceOf
can't actually check the cast that it does. 由于类型擦除,类型
T
在运行时是未知的,因此asInstanceOf
不能实际检查其类型转换。 In fact, it compiles as a no-op. 实际上,它作为无操作编译。 However, when the
.get
is finally done a cast is made to Double
, and because the type is known here we can get a ClassCastException
. 但是,最终完成
.get
时,将对Double
进行.get
类型转换,并且由于这里知道类型,因此我们可以获得ClassCastException
。
If you change convertAsTypeOf
to use ClassTag
: 如果更改
convertAsTypeOf
使用ClassTag
:
def convertAsTypeOf[T](anyValue: Any)(implicit tag: ClassTag[T]): Try[T] =
Try(tag.runtimeClass.cast(anyValue).asInstanceOf[T])
You will then get errors when you expect: 然后,您将在预期的时候得到错误:
scala> convertAsTypeOf[Double]("abc")
res1: scala.util.Try[Double] = Failure(java.lang.ClassCastException: Cannot cast java.lang.String to double)
The ClassTag
represents the type T
at runtime, allowing the value to be checked against it. ClassTag
在运行时表示类型T
,从而可以根据该值检查值。
The reason this happens is type erasure, which makes asInstanceOf[T] for generic T useless. 发生这种情况的原因是类型擦除,这使得通用T的asInstanceOf [T]无效。 I don't know why the compiler doesn't issue any warning.
我不知道为什么编译器不会发出任何警告。
You can force the check to happen by using a ClassTag. 您可以使用ClassTag强制进行检查。 Something like this:
像这样:
import reflect.ClassTag
def convertAsTypeOf[T : ClassTag](anyValue: Any): Try[T] = Try {
anyValue match { case t: T => t }
}
This works because the compiler will use the implicit ClassTag in the case match if it is available (and generate a warning if it is not). 之所以可行,是因为如果大小写匹配,编译器将使用隐式ClassTag(如果可用)(如果不可用,则生成警告)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.