Kotlin-Sternchenoperator vor Variablenname oder Spread-Operator in Kotlin

96

Ich möchte wissen, was genau ein Sternchen vor dem Variablennamen in Kotlin tut. Ich habe dies ( *args) bei Spring Boot Kotlin gesehen Beispiel :

@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)
}
mojtab23
quelle

Antworten:

159

Der *Operator ist in Kotlin als Spread Operator bekannt .

Aus der Kotlin-Referenz ...

Wenn wir eine vararg-Funktion aufrufen, können wir Argumente einzeln übergeben, z. B. asList (1, 2, 3), oder wenn wir bereits ein Array haben und dessen Inhalt an die Funktion übergeben möchten, verwenden wir den Spread Operator (stellen Sie dem Array * voran):

Es kann auf ein Array angewendet werden, bevor es an eine akzeptierende Funktion übergeben wird varargs.

Beispielsweise...

Wenn Sie eine Funktion haben, die eine unterschiedliche Anzahl von Argumenten akzeptiert ...

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

Sie können ein Array wie folgt übergeben ...

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

Anmerkungen:

  • Der *Operator ist (natürlich) auch der Multiplikationsoperator .
  • Der Operator kann nur verwendet werden, wenn Argumente an eine Funktion übergeben werden. Das Ergebnis der Operation kann nicht gespeichert werden, da es keinen Wert ergibt (es ist rein syntaktischer Zucker).
  • Der Operator kann einige C / C ++ - Programmierer zunächst verwirren, da es so aussieht, als würde ein Zeiger de-referenziert. Es ist nicht; Kotlin hat keine Ahnung von Zeigern .
  • Der Operator kann beim Aufrufen einer vararg-Funktion zwischen anderen Argumenten verwendet werden. Dies wird im Beispiel hier gezeigt .
  • Der Operator ähnelt der applyFunktion in verschiedenen funktionalen Programmiersprachen.
byxor
quelle
Ist das Inline-Array des Spread-Operators? Zum Beispiel für Array a = [1, 2, 3] funWithVararg (* a) wird in funWithVararg (1,2,3) eingefügt? Ich meine in Bytecode-Ebene.
David
22

Zusätzlich zu den Antworten, die direkt auf "Was ist das für ein Ding!?!" Waren, haben Sie häufig den Fall, dass Sie eine haben Listund diese an eine Funktion übergeben möchten, die eine erwartet vararg. Dafür lautet die Konvertierung:

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

Angenommen, der letzte Parameter von someFuncist varargvom gleichen Typ wie die Elemente in der Liste.

Jayson Minard
quelle
Ich danke dir sehr! Dies sollte in den offiziellen Dokumenten unter dem Abschnitt "Spread Operator" enthalten sein, auf den Sie achten sollten, wenn Ihr Spread Operator nicht funktioniert.
erfreut
Vielen Dank! Wirklich hilfreich. Sie fragen sich, was "Spread Operator" hinter den Kulissen ist? Ist nur ein Weg, um einen Varargs-Wert zu erhalten?
Nicolas Jafelle
11

Wie in der Dokumentation beschrieben, handelt es sich um einen Spread-Operator:

Wenn wir eine vararg-Funktion aufrufen, können wir Argumente einzeln übergeben, z. B. asList (1, 2, 3), oder wenn wir bereits ein Array haben und dessen Inhalt an die Funktion übergeben möchten, verwenden wir den Spread Operator (stellen Sie dem Array * voran):

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

Wenn eine Funktion, die einen vararg-Parameter (Variable Anzahl der Argumente) akzeptiert, wie folgt lautet:

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

Um diese Methode aufzurufen, können wir Folgendes tun:

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

Aber was ist, wenn wir diesen Wert in einem Array haben, wie:

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

Um diese Methode aufzurufen, müssen wir den Spread-Operator verwenden, wie:

 sum(*array)

Hier übergibt * (Spread-Operator) den gesamten Inhalt dieses Arrays.

* Array entspricht 1,2,3,4,5

Aber warte eine Minute, was ist, wenn wir es so nennen: sum(array) Es gibt uns einen Fehler bei der Kompilierungszeit von Type Mismatch:

Type mismatch.
Required:Int
Found:IntArray

Das Problem ist, dass die sumFunktion einen vararg IntParameter akzeptiert (der einen Wert wie: 1,2,3,4,5 akzeptiert). Wenn wir ein Array übergeben, wird es als übergeben IntArray.

Suraj Vaishnav
quelle
4

In Java können *Sie ein Array unverändert übergeben. Ein Vorteil beim Entpacken eines Arrays mit dem Spread-Operator besteht jedoch darin, dass Sie mit dem Spread-Operator die Werte eines Arrays und einige feste Werte in einem einzigen Aufruf kombinieren können. Java unterstützt dies nicht.

Gulzar Bhat
quelle
Upvoted, weil ich mich gefragt habe, warum sie es so implementiert haben. Ich bin mir immer noch nicht 100% sicher. Ich meine, konnten sie das in den meisten Fällen nicht einfach ableiten?
Tim Büthe
1
@ TimBüthe In einigen Fällen wäre es nicht möglich, darauf zu schließen, betrachten Sie die folgenden Fälle val resultOne = arrayOf(intArrayOne, intArrayTwo)und val resultTwo = arrayOf(*intArrayOne, *intArrayTwo). Art von resultOneund resultTwosind jeweils Array<Int>und Array<Array<Int>>. Ich glaube, das ist einer der Gründe
Farid