ScalaのArrayはjavaの配列

## まず

まずはArrayの[ドキュメント](http://docs.scala-lang.org/ja/overviews/collections/arrays.html)を読んでみよう。

- ScalaのArrayはjavaの配列で実装してる
- ArrayOpsへの暗黙変換でコレクションのメソッド使える
- 列(Seq)として扱う場合は、WrappedArrayだ
- ジェネリック配列遅い

とのこと。

## 比較

Arrayは==で比較できない。

```scala
scala> Array(1) == Array(1)
res0: Boolean = false
```

よく分からんので、実際に逆コンパイルして結果を見てみる。

```scala
class Main {
  def main(args: Array[String]) = {
    Array(1,2,3) == Array(1,2,3)
  }
}
```

```scala
$ scalac a.scala && jad -p Main.class

public class Main
{

    public boolean main(String args[])
    {
        return (new int[] {
            1, 2, 3
        }) == (new int[] {
            1, 2, 3
        });
    }

    public Main()
    {
    }
}
```

闇の力によってjavaの配列になった。

ということは...。

```scala
scala> java.util.Arrays.equals(Array(1,2), Array(1,2))
res1: Boolean = true
```

なるほ。

sameElementsで比較すれば大丈夫と言われている。

```scala
class Main {
  def main(args: Array[String]) = {
    Array(1,2) sameElements Array(1,2)
  }
}
```

```scala
$ scalac a.scala && jad -p Main.class

import scala.Predef$;
import scala.collection.mutable.ArrayOps;

public class Main
{

    public boolean main(String args[])
    {
        return Predef$.MODULE$.intArrayOps(new int[] {
            1, 2
        }).sameElements(Predef$.MODULE$.wrapIntArray(new int[] {
            1, 2
        }));
    }

    public Main()
    {
    }
}
```

sameElementsはGenIterableを渡す必要があるが、ArrayOpsはそれを継承していないので、継承してるWrappedArrayが使われてる。

## ジェネリックなArray

ドキュメントによると、ClassManifestでなんかやってるとある。今だとClassTagだ。

試してみる。これは逆コンパイルせずとも分かる。

```scala
def f[T: reflect.ClassTag](xs: T*): Array[T] = new Array[T](xs.length)
```

```scala
$ scala -Xprint:typer -e 'def f[T: reflect.ClassTag](xs: T*): Array[T] = new Array[T](xs.length)'

[[syntax trees at end of                     typer]] // scalacmd48703904896790885.scala
package <empty> {
  object Main extends scala.AnyRef {
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    };
    def main(args: Array[String]): Unit = {
      final class $anon extends scala.AnyRef {
        def <init>(): <$anon: AnyRef> = {
          $anon.super.<init>();
          ()
        };
        private def f[T](xs: T*)(implicit evidence$1: scala.reflect.ClassTag[T]): Array[T] = evidence$1.newArray(xs.length)
      };
      {
        new $anon();
        ()
      }
    }
  }
}
```

`new Array[T](xs.length)`が、闇の力によってClassTagのnewArrayに変換された。

newArrayは、

```scala:ClassTag.scala
  override def newArray(len: Int): Array[T] =
    runtimeClass match {
      case java.lang.Byte.TYPE      => new Array[Byte](len).asInstanceOf[Array[T]]
      case java.lang.Short.TYPE     => new Array[Short](len).asInstanceOf[Array[T]]
      case java.lang.Character.TYPE => new Array[Char](len).asInstanceOf[Array[T]]
      case java.lang.Integer.TYPE   => new Array[Int](len).asInstanceOf[Array[T]]
      ...
      case _                        => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
    }
```

`new Array[Int](len)` は `new int[len]` に変換される。

```scala
class Main {
  def main(args: Array[String]) = {
    new Array[Int](3)
  }
}

は

public int[] main(String args[])
{
    return new int[3];
}

に変換される...。
```

分からんけど分かった。

![](http://tiqav.com/5K4.jpg)