我试图了解Cast如何在Scala中工作。这是示例:
object Main extends App {
val ai: Array[Any] = Array(1, 2, 3, 4, 5, 6)
val ar: Array[AnyRef] = ai.map(_.asInstanceOf[AnyRef])
}
而且效果很好。 https://ideone.com/6PerTR
现在让我们将其重写如下:
object Main extends App {
val ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
val ar: Array[AnyRef] = ai.asInstanceOf[Array[Any]].map(_.asInstanceOf[AnyRef])
}
这是行不通的。失败,现在
ClassCastException
为https://ideone.com/JbOQbb。为什么?我以为在这里添加演员就足够了吗?为什么第一个示例有效?如果我们先将
AnyRef
转换为Array[Any]
,如何在第二种情况下使其工作?如何在这里添加拳击?UPD:我也尝试过:
object Main extends App {
val ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
val aii: Array[Any] = ai.asInstanceOf[Array[Any]]
val ar: Array[AnyRef] = aii.map(_.asInstanceOf[AnyRef])
}
但是得到了
ClassCastException
https://ideone.com/ZcgT6x。它看起来与第一个示例非常相似。在这种情况下,如何将aii
转换为Array[AnyRef]
? 最佳答案
TL; DR:第一个代码段有效,因为在生成数组时自动装箱已经发生。第二个代码段不起作用,因为创建的数组是Array[Int]
。
即使Int
是Any
的子类型,Array[Int]
不是Array[Any]
的子类型。因此,当你写
scala> val ai: Array[Any] = Array(1, 2, 3, 4, 5, 6)
ai: Array[Any] = Array(1, 2, 3, 4, 5, 6)
这基本上等于
val ai: Array[Any] = Array[Any](1, 2, 3, 4, 5, 6)
这样所有整数都已装箱。结果是:
scala> ai.getClass
res0: Class[_ <: Array[Any]] = class [Ljava.lang.Object;
也就是说,您的
ai
从一开始就本质上就是Array[Object]
。第二个片段中的关键区别在于,即使
Array[Int]
不是Array[Any]
的子类型,它肯定是AnyRef
的子类型,因此没有自动装箱:
scala> val ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
scala> ai.getClass
res2: Class[_ <: AnyRef] = class [I
如您所见,
AnyRef
是带有未装箱的整数的int
-array。如果现在尝试将未装箱的int数组转换为
Array[Any]
,则您获取类强制转换异常。
您可以通过强制立即自动装箱来修复第二个示例,如下所示:
object Main extends App {
val ai: AnyRef = Array[Any](1, 2, 3, 4, 5, 6)
val ar: Array[AnyRef] =
ai.asInstanceOf[Array[Any]].map(_.asInstanceOf[AnyRef])
}
或者,您也可以将数组转换为正确的类型,即
Array[Int]
:object Main extends App {
val ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
val ar: Array[AnyRef] =
ai.asInstanceOf[Array[Int]].map(_.asInstanceOf[AnyRef])
}