前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scala 谜题 - 有趣的类型转换

Scala 谜题 - 有趣的类型转换

作者头像
joymufeng
发布2018-05-17 15:53:04
7500
发布2018-05-17 15:53:04
举报

在 Scala 中,List[String] 和 List[Int] 之间并没有继承关系,但是下面的代码竟然可以通过编译并且顺利运行:

代码语言:javascript
复制
object Test extends App {
  val strList: List[String] = List("a", "b", "c")
  val strToIntList: List[Int] = strList.asInstanceOf[List[Int]]
  println(strToIntList)
}

输出:

代码语言:javascript
复制
//输出: List(a, b, c)

是的,你没看错!我们把 List[String] 成功的转换成了 List[Int] 类型。事实上真的是这样吗? 让我们来测试一下:

代码语言:javascript
复制
object Test extends App {
  val strList: List[String] = List("a", "b", "c")
  val strToIntList: List[Int] = strList.asInstanceOf[List[Int]]
  val head = strToIntList(0)
  println(head)
}

输出:

代码语言:javascript
复制
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:101)
    ...
	at test.Test.main(Test.scala)

哈哈,抛出了类型转换异常。编译器推断出 head 类型为 Int 型,但在运行时却被赋予了 String 型,所以导致了运行时错误。

翻看 Scala 文档终于找到了原因:

final def asInstanceOf[T0]: T0

Cast the receiver object to be of type T0.

Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression 1.asInstanceOf[String]will throw a ClassCastException at runtime, while the expression List(1).asInstanceOf[List[String]] will not. In the latter example, because the type argument is erased as part of compilation it is not possible to check whether the contents of the list are of the requested type.

在调用 asInstanceOf 方法时,编译器给予开发者足够的信任,认为你有足够的理由去这样做。但是在运行时,由于泛型类的类型参数被擦除了,所以 List[String] 和 List[Int] 在运行时都是 List 类型,但是在操作其元素时要格外小心,否则会抛出类型转换异常。

利用这个特性我们可以写出一些很有意思的代码,虽然 Class[T] 是 invariant 的,利用 asInstanceOf 方法可以让它变成 covariant,示例代码如下:

代码语言:javascript
复制
object Test extends App {
  val jsObjClass:   Class[JsObject] = classOf[JsObject]
  val jsValueClass: Class[JsValue]  = jsObjClass.asInstanceOf[Class[JsValue]]
}

由于在运行时 JsObject 可以被成功地转换为 JsValue,所以上述代码可以正常工作。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档