1. 概要

この簡単な記事では、 IntArray配列 Kotlinで。 もちろん、他の特殊なプリミティブ配列にも違いを一般化できます。

せっかちな人のために、Kotlinはアレイをコンパイルします内部でInteger[]に、IntArrayをint[]に 。 正当な理由がない限り、より効率的な表現であるため、後者を使用することをお勧めします。

それでは、詳細を詳しく見ていきましょう。

2. さまざまな配列表現

JVMをターゲットにする場合、Kotlinコンパイラはその配列をJVM配列として表します。 言語レベルでは、Kotlinは2セットの配列を提供します。

  • The 配列 type。typeパラメーターは、次のような任意のKotlinタイプにすることができます。 配列また配列
  • IntArrayなどの特殊なプリミティブ配列

主にJVMが2つの方法で配列を作成および操作できるため、これら2つの形式があります。

  • newarray オペコードは、プリミティブタイプ int など)の配列を作成し、 * astore iastore int )および * aloadオペコードの配列の場合は
  • anewarray オペコードは、参照型の配列を作成し、aastoreおよびaaloadオペコードで操作します。

特殊なプリミティブオペコードにより、JVMはプリミティブ配列の作成と操作を最適化できます。

理論についてもう少し理解できたので、これら2つのタイプの配列のバイトコード表現を比較してみましょう。

3. The 配列バイトコード表現

アクションの違いを確認するために、簡単なスニペットを考えてみましょう。

val arrayOfInts = arrayOf<Int>(42)

ここで、推論されるタイプはもちろん、 配列 。 生成されたバイトコードを確認するには、まず、Kotlinコードをコンパイルする必要があります。

>> kotlinc Arrays.kt

これで、 javap ツールを使用して、生成されたバイトコードをチェックアウトできます。 とにかく、これはJVMが配列を作成する方法です。

>> javap -c -p ArraysKt
0: iconst_1
1: anewarray     #8      // class java/lang/Integer

だから、アレイ Kotlinでは、java.lang.Integer(Integer [])の配列に変換されています anewarray 命令は、サイズ1の配列( iconst_1 ビット)を作成します。 これはKotlinでの配列の表現としてはかなり非効率的であり、null値を格納する必要がある場合にのみ使用する必要があります。

最初の配列要素を42に設定するために、JVMは変換を実行します。

6: iconst_0
7: bipush        42
9: invokestatic  #12    // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
12: aastore

JVMは、Integer.valueOf(int)静的メソッドを呼び出すことにより、リテラル42を整数インスタンスに変換します。 だから、私たちが何かを追加するたびに配列 、不要プリミティブ値のボクシングボンネットの下で起こります、もう一つの非効率的なビット!

4. IntArrayバイトコード表現

KotlinでIntArrayを作成し、1つの要素で初期化してみましょう。

val intArray = intArrayOf(42)

コンパイル後、JVMが次のようにこの配列を作成することがわかります。

15: iconst_1
16: newarray   int

上記のように、JVMは特殊な newarray 命令を使用して、プリミティブint値の配列を作成します。 したがって、IntArrayはバイトコードレベルでint[]に変換されています。

ご想像のとおり、このような配列へのロードと保存は、不要なボックス化やボックス化解除なしで実装されます。

20: iconst_0
21: bipush     42
23: iastore

ここで、JVMは、リテラル42をそのまま、ボックス化せずに最初の要素として配列に格納します。

5. 結論

この記事では、プリミティブ配列とそれに対応する配列について学びました配列タイプは、JVM表現とAPIの点で異なります。 つまり、 null 値をこれらのプリミティブと一緒に格納する必要がない限り、IntArrayおよびその他の特殊なプリミティブ配列を使用することをお勧めします。