Scala - 如何将通用列表转换为数组并避免 "No ClassTag available for T"

Scala - How to Convert Generic List To Array and avoid "No ClassTag available for T"

我正在研究一段应该是微不足道的代码。我想获取一个列表,并将其转换为等效的数组:

import scala.collection.JavaConverters

object Help extends App {
  def f1[T](lst: List[T]) = {
    lst.toArray
  }

  val x = List(1, 2, 3)
  println(f1(x))
}

运行 此代码给出:

"No ClassTag available for T"

我怎样才能避免这个问题;我来自 Python 背景,所以希望得到能让我理解这里的机制的回复。

谢谢!

尝试像这样添加隐式 ClassTag 参数

import scala.reflect.ClassTag

def f1[T](lst: List[T])(implicit ev: ClassTag[T]) = {
  lst.toArray
}

如果我们看一下 toArray

的签名,原因就很清楚了
def toArray[B >: A: ClassTag]: Array[B]

相当于

def toArray[B >: A](implicit ev: ClassTag[B]): Array[B]

所以你必须将隐式参数从 f1 向下传递到 toArray

would appreciate a response that gives me an understanding of the mechanics here

关键是要了解 Array 不是 真正的 Scala 集合。这一次,它不是 Iterable

的子类型
implicitly[Array[Int] <:< Iterable[Int]] // error

Array 和真正的 Scala 集合之间的另一个区别是真正的 Scala 集合不需要 ClassTag。这样做的原因是 Scala 集合经历了一个类型擦除过程,这意味着运行时知道它是一个 List 但不区分 List[Int]List[String],例如。然而,这不适用于 Array。在运行时 Array[Int]Array[String] 之间确实存在差异。因此 ClassTag 是一种发明的机制,用于携带仅在编译时存在的类型信息到运行时,因此 Array 可以具有 Java.

中的行为

你还会遇到其他的区别,比如

Array(42) == Array(42)  // false
List(42) == List(42)    // true

最佳做法是尽可能避免Array