Scala Array.apply 的魅力是什么

Cha*_*ang 3 arrays reflection types scala scala-2.10

从 scala-2.10.4 的 array.scala 中,数组被定义为

final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {    
  /** The length of the array */
  def length: Int = throw new Error()
  def apply(i: Int): T = throw new Error()
  def update(i: Int, x: T) { throw new Error() }
  override def clone(): Array[T] = throw new Error()
}
Run Code Online (Sandbox Code Playgroud)

请注意,apply 方法会抛出异常!对于伴随对象 Arrry,我找到以下代码:

  def apply[T: ClassTag](xs: T*): Array[T] = {
    val array = new Array[T](xs.length)
    var i = 0
    for (x <- xs.iterator) { array(i) = x; i += 1 }
    array
  }
Run Code Online (Sandbox Code Playgroud)

我知道有一个隐式参数是ClassTag[T],让我惊讶的是如何

新数组[T] (xs.length)

被编译。通过反编译 Array.class,我发现该行被转换为:

public <T> Object apply(Seq<T> xs, ClassTag<T> evidence$2)
{
    // evidence$2 is implicit parameter
    Object array = evidence$2.newArray(xs.length());
    ...  
}
Run Code Online (Sandbox Code Playgroud)

我真的被这种翻译弄糊涂了,这里面的规则是什么?

谢谢张

Noa*_*oah 5

ScalaArray类只是运行时的一个虚假包装器,因此您可以在 Scala 中使用数组。您可能会感到困惑,因为Array类中的那些方法会抛出异常。他们这样做的原因是,如果您实际上最终使用假类,它会爆炸,因为它实际上应该使用 java 运行时数组,它没有像 Scala 这样的合适的容器类。您可以在此处查看编译器如何处理它。当您在 Scala 中使用数组时,您可能还使用了一些来自 predef 之类的隐式ArrayOpsWrappedArray额外的辅助方法。

TLDR:Scala 编译器魔法使数组在底层与 java 运行时一起工作。