Java代码:
Collection<MethodInfo> items = getItems();
MethodInfo[] itemsArray = items.toArray(new MethodInfo[items.size()]);
我想知道,Scala中的等效代码是什么?
val items: Seq[MethodInfo] = getItems
val itemsArray: Array[MethodInfo] = ???
答案 0 :(得分:7)
正如@SpiderPig在他的评论中指出的那样,你可以简单地调用items.toArray
将序列转换为数组。我想你可能会因为你必须用Java提供一个目标数组而感到困惑,但在Scala中你只需要调用toArray
而没有参数。
您必须使用Java提供数组的原因与type erasure有关。 Java编译器不知道在编译时要创建什么类型的数组,并且由于Java数组不是通用的,因此需要具体类型才能实例化。
toArray
的Java实现使用一种技巧来解决这个限制。通过传入所需类型的数组,JVM可以使用 数组上的反射来实例化数组,以创建正确类型的新数组。 (您实际上可以将0元素数组传递给toArray
方法,它将分配一个正确大小的数组。toArray
方法实际上将此工作委托给Arrays.copyOf
,然后使用implementation for toArray
用于创建副本的反射。)
Scala采用了不同的方法。与Java编译器(默认参数,隐式转换,隐式参数等)相比,Scala编译器在幕后做了更多工作。如果你看一下{{3}}:
,你可以看出有一些编译器魔法在起作用def toArray[B >: A : ClassTag]: Array[B] = {
if (isTraversableAgain) {
val result = new Array[B](size)
copyToArray(result, 0)
result
}
else toBuffer.toArray
}
泛型类型中的ClassTag
要求编译器提供类信息。这允许JVM为最终结果实例化正确类型和大小的数组。这意味着您不必提供数组,因为Scala库可以为您创建一个正确的类型和大小。
答案 1 :(得分:2)
Java中存在Collection#toArray(T[] a)
的唯一原因是类型擦除。在运行时,Java不知道T
是什么类型,因此无法创建类型为T[]
的数组。由于您必须自己创建一个正确类型的数组,因此最好分配一个正确的大小以避免浪费空间或让Java分配另一个。
如果使用Collection#toArray()
代替(不传递数组),Java将自动分配一个正确大小的数组,但由于没有类型信息,它将为Object[]
。
Scala的toArray方法有点先进:
def toArray[B >: A](implicit arg0: ClassTag[B]): Array[B]
基本上,它使用隐式参数来提供运行时类型信息,因此可以自动实例化正确类型的数组。您可以使用@ SpiderPig的代码而无需自己创建阵列,也不必担心大小。