変数名の前のKotlinアスタリスク演算子またはKotlinのスプレッド演算子


97

Kotlinで変数名の前にアスタリスクが正確に何をするのか知りたい。私はこれ*argsSpring boot Kotlinの例で見ました:

@SpringBootApplication
open class Application {

    @Bean
    open fun init(repository: CustomerRepository) = CommandLineRunner {
        repository.save(Customer("Jack", "Bauer"))
        repository.save(Customer("Chloe", "O'Brian"))
        repository.save(Customer("Kim", "Bauer"))
        repository.save(Customer("David", "Palmer"))
        repository.save(Customer("Michelle", "Dessler"))
    }
}

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}

回答:


161

*オペレータは次のように知られているスプレッドオペレータ Kotlinインチ

Kotlinリファレンスから...

vararg-functionを呼び出すときに、引数を1つずつ渡すことができます(例:asList(1、2、3))。または、すでに配列があり、その内容を関数に渡したい場合は、spreadを使用します。演算子(配列の前に*を付けます):

を受け入れる関数に渡す前に、配列に適用できますvarargs

例えば...

さまざまな数の引数を受け入れる関数がある場合...

fun sumOfNumbers(vararg numbers: Int): Int {
    return numbers.sum()
}

あなたはそれに配列をそれに渡すことができます...

val numbers = intArrayOf(2, 3, 4)
val sum = sumOfNumbers(*numbers)
println(sum) // Prints '9'

ノート:

  • *また、オペレータは、ある乗算演算子(もちろん)。
  • 演算子は、引数を関数に渡す場合にのみ使用できます。値が得られないため、操作の結果を保存できません純粋に構文上の砂糖です)。
  • ポインターが逆参照されているように見えるため、オペレーターは最初に一部のC / C ++プログラマーを混乱させる可能性があります。そうではありません。Kotlinにはポインタの概念はありません
  • 演算子は、vararg関数を呼び出すときに他の引数の間に使用できます。これは、ここの例示されています
  • 演算子はapply、さまざまな関数型プログラミング言語の関数に似ています。

Spreadオペレーターはインライン配列ですか?たとえば、配列a = [1、2、3]の場合funWithVararg(* a)はfunWithVararg(1,2,3)にインライン化しますか?私はバイトコードレベルで意味します。
デビッド

22

「これは何ですか!?!」に直接向けられた回答に加えて、をList期待している関数にそれを渡したい場合がありますvararg。このための変換は次のとおりです。

someFunc(x, y, *myList.toTypedArray())

最後のパラメータがあると仮定するとsomeFuncされvararg、リスト内の要素と同じタイプの。


どうもありがとうございます!これは、スプレッドオペレーターが機能していないときに注意する必要があるものとして、スプレッドオペレーターセクションの公式ドキュメントにあるはずです。
pleasedesktop

ありがとう!本当に役に立ちました。裏で「スプレッドオペレーター」とは何ですか。可変引数の値を取得する方法にすぎませんか?
Nicolas Jafelle 2017年

11

ドキュメントで説明されているようにこれはスプレッドオペレーターです。

vararg-functionを呼び出すときに、引数を1つずつ渡すことができます(例:asList(1、2、3))。または、すでに配列があり、その内容を関数に渡したい場合は、spreadを使用します。演算子(配列の前に*を付けます):

val a = arrayOf(1, 2, 3) 
val list = asList(-1, 0, *a, 4)

5

次のようなvararg(引数の変数数)パラメータを受け入れる関数の場合:

fun sum(vararg data:Int)
{
   // function body here         
}

このメソッドを呼び出すために、次のことができます。

sum(1,2,3,4,5)

しかし、これらの値が配列にある場合はどうなるでしょうか。

val array= intArrayOf(1,2,3,4,5)

次に、このメソッドを呼び出すには、次のようなスプレッド演算子を使用する必要があります。

 sum(*array)

ここで、*(スプレッド演算子)はその配列のすべてのコンテンツを渡します。

*配列1、2、3、4、5と同等

しかし、少し待ってsum(array) ください。次のように呼び出すとどうなるでしょうか。タイプミスマッチのコンパイル時エラーが発生します。

Type mismatch.
Required:Int
Found:IntArray

問題は、sum関数がvararg Intパラメーターを受け入れることです(これは、1,2,3,4,5のような値を受け入れます)IntArray。配列を渡す場合、それはとして渡されます。


4

Javaでは配列をそのまま渡すことができますが、spread演算子で配列をアンパックする利点*は、spread演算子を使用すると、配列の値と一部の固定値を1回の呼び出しで結合できることです。Javaはこれをサポートしていません。


なぜ彼らがこのようにそれを実装したのか自分に尋ねたので、賛成した。私はまだそれについて100%確信が持てません。つまり、ほとんどの場合、これを推測することはできないのでしょうか。
TimBüthe19年

1
@TimBüthe場合によっては、それを推測することができない可能性がval resultOne = arrayOf(intArrayOne, intArrayTwo)ありval resultTwo = arrayOf(*intArrayOne, *intArrayTwo)ます。以下のケースとを検討してください。種類resultOneresultTwoそれぞれArray<Int>Array<Array<Int>>。それが理由の1つだと思います
Farid
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.