如何在Scala中进行拳击?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Scala中进行拳击?相关的知识,希望对你有一定的参考价值。
我试图了解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
阵列。
如果你现在尝试将一个未装箱的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])
}
由于在字节码级别没有Any
类型的表示,因此Array[Any]
和Array[AnyRef]
都需要将元素装箱。因此,当试图从Array[Int]
施放到Array[Any]
时,我们实际上是从[I
施放到[java/lang/Object;
,这是一个例外。
唯一的通用解决方案是专门处理每种基本类型的数组,使用WrappedArray
可以很容易地完成:
val ai: AnyRef = Array(1, 2, 3, 4, 5, 6)
val ar: Array[AnyRef] = collection.mutable.WrappedArray.make(ai).toArray
以上是关于如何在Scala中进行拳击?的主要内容,如果未能解决你的问题,请参考以下文章