KotlinのVarargsおよびSpread演算子
1. 概要
このクイックチュートリアルでは、Kotlinの関数に可変数の引数を渡す方法を学習します。 また、Kotlinを使用して配列をvarargに変換する方法についても説明します。
最後に、これらすべてがバイトコードレベルでどのように表されるかを見ていきます。
2. Varargs
関数に可変数の引数を渡すには、varargパラメーターを使用してその関数を宣言する必要があります。
fun sum(vararg xs: Int): Int = xs.sum()
これは、sum()関数が0個以上の整数を受け入れることができることを意味します。 例えば:
val zeroNumbers = sum()
assertEquals(0, zeroNumbers)
assertEquals(2, sum(2))
assertEquals(12, sum(2, 4, 6))
上に示したように、vararg引数に0個以上のパラメーターを渡すことができます。
関数本体の内部では、varargパラメーターを配列として扱うことができます。
fun <T> printAll(vararg ts: T) {
ts.forEach { println(it) }
}
参照型のvarargの場合、varargパラメーターはその参照型のArrayとして扱われます。 たとえば、上記の例では、 ts パラメータは、としてアクセス可能になります配列
fun printStrings(vararg vs: String) {
vs.forEach { println(it) }
}
ただし、プリミティブ型の場合、varargパラメーターは*Array特殊配列型のように機能します。
3. 制限事項
各関数は最大で1つのvarargパラメーターを持つことができます。 複数のvarargパラメーターを使用して関数を宣言すると、Kotlinコンパイラーは次のエラーで失敗します。
Kotlin: Multiple vararg-parameters are prohibited
他の多くのプログラミング言語とは異なり、varargパラメーターを最後のパラメーターとして宣言する必要はありません:
fun createUser(vararg roles: String, username: String, age: Int) {
// omitted
}
ただし、 vararg が最後に宣言されたパラメーターでない場合は、あいまいさを避けるために、他のパラメーターを名前で渡す必要があります。
createUser("admin", "user", username = "me", age = 42)
そうしないと、コンパイラはエラーで失敗します。
4. スプレッド演算子
Kotlinに既存の配列インスタンスがあり、それをvarargを受け入れる関数に渡したい場合があります。そのような状況では、配列を vararg に分解するには、次を使用できます。スプレッド演算子:
val numbers = intArrayOf(1, 2, 3, 4)
val summation = sum(*numbers)
assertEquals(10, summation)
numbers配列変数の後ろにある“ *”はspread演算子です。
5. バイトコード表現
内部では、KotlinはそのvarargsをJavavarargsに変換します。 これを確認するために、kotlincを介してKotlinソースコードをコンパイルしましょう。
$ kotlinc Vararg.kt
その後、javapを介して生成されたバイトコードを確認できます。
$ javap -c -p -v com.baeldung.varargs.VarargKt
public static final int sum(int...);
descriptor: ([I)I
flags: (0x0099) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_VARARGS
// truncated
上記のように、 vararg パラメータは、Javaではvarargとして定義されています。 また、 ACC_VARARGS フラグは、関数が可変長パラメーターを受け入れることを指定します。
さらに、スプレッド演算子を使用する場合:
val numbers = intArrayOf(1, 2)
sum(*numbers)
KotlinはArrays.copyOf(array、length)メソッドを使用して、最初に拡散配列のコピーを作成します。 次に、新しい配列をvarargパラメーターとして渡します。
12: aload_0 // loads the int[]
13: dup
14: arraylength
15: invokestatic #71 // Method java/util/Arrays.copyOf:([II)[I
18: invokestatic #72 // Method sum:([I)I
インデックス13と14は、2つのパラメータをオペランドスタックにロードし、それらを Arrays.copyOf(int []、int)メソッドに渡します。 基本的に、元の配列から新しい配列にすべての要素をコピーし、コピーした要素を sum()関数に渡します。
Javaでは、varargパラメーターを最後のパラメーターとして宣言する必要があります。 したがって、Kotlinの最後のパラメーターを除く任意の位置で vararg パラメーターを宣言すると、次のようになります。
fun createUser(vararg roles: String, username: String, age: Int) {
// omitted
}
コンパイラはその特定のvarargを単純な配列に変換します:
public static final void createUser(java.lang.String[], java.lang.String, int);
descriptor: ([Ljava/lang/String;Ljava/lang/String;I)V
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ご覧のとおり、Kotlinコンパイラは「varargroles:String」を、予想される「String…」構文ではなく「String[]」に変換しました。
6. 結論
この短いチュートリアルでは、Kotlinでvarargパラメーターがどのように機能するかを学びました。 さらに、spread演算子を使用して、Kotlinの既存の配列タイプをvarargに変換する方法を確認しました。
いつものように、すべての例はGitHubでから入手できます。