Operator tanda bintang Kotlin sebelum nama variabel atau Operator Penyebaran di Kotlin

102

Saya ingin tahu apa sebenarnya yang dilakukan asterisk sebelum nama variabel di Kotlin. Saya melihat ini ( *args) dalam contoh Spring 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)
}
mojtab23
sumber

Jawaban:

169

The *Operator dikenal sebagai operator Penyebaran di Kotlin.

Dari Referensi Kotlin ...

Ketika kita memanggil sebuah vararg-function, kita bisa mengirimkan argumen satu per satu, misalnya asList (1, 2, 3), atau, jika kita sudah memiliki sebuah array dan ingin meneruskan isinya ke fungsi tersebut, kita menggunakan spread operator (awali array dengan *):

Ini dapat diterapkan ke Array sebelum meneruskannya ke fungsi yang menerima varargs.

Sebagai contoh...

Jika Anda memiliki fungsi yang menerima sejumlah argumen yang bervariasi ...

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

Anda dapat memasukkan array ke dalamnya seperti ...

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

Catatan:

  • The *Operator juga merupakan operator perkalian (tentu saja).
  • Operator hanya bisa digunakan saat meneruskan argumen ke suatu fungsi. Hasil operasi tidak dapat disimpan karena tidak menghasilkan nilai (ini murni gula sintaksis).
  • Operator mungkin membingungkan beberapa programmer C / C ++ pada awalnya karena sepertinya pointer sedang de-referensi. Ini tidak; Kotlin tidak memiliki gagasan tentang pointer .
  • Operator bisa digunakan di antara argumen lain saat memanggil fungsi vararg. Ini ditunjukkan dalam contoh di sini .
  • Fungsi operator mirip dengan applyberbagai bahasa pemrograman fungsional.
byxor
sumber
Apakah array sebaris operator Spread? Misalnya untuk array a = [1, 2, 3] funWithVararg (* a) inlines menjadi funWithVararg (1,2,3)? Maksud saya di level bytecode.
David
23

Selain jawaban yang langsung mengarah ke "apa ini!?!", Anda sering memiliki kasus di mana Anda memiliki Listdan ingin meneruskannya ke fungsi yang mengharapkan a vararg. Untuk ini, konversinya adalah:

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

Dengan asumsi bahwa parameter terakhir dari someFuncadalah varargjenis yang sama dengan elemen dalam daftar.

Jayson Minard
sumber
Terima kasih banyak! Ini harus ada di dokumen resmi di bawah bagian operator penyebaran sebagai sesuatu yang harus diperhatikan ketika operator penyebaran Anda tidak berfungsi.
desktop
Terima kasih! Sangat membantu. Ingin tahu apa itu "Operator Penyebaran" di balik layar? Apakah hanya cara untuk mendapatkan nilai varargs?
Nicolas Jafelle
11

Seperti yang dijelaskan dalam dokumentasi, ini adalah operator penyebaran:

Ketika kita memanggil sebuah vararg-function, kita bisa mengirimkan argumen satu per satu, misalnya asList (1, 2, 3), atau, jika kita sudah memiliki sebuah array dan ingin meneruskan isinya ke fungsi tersebut, kita menggunakan spread operator (awali array dengan *):

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

Jika fungsi yang menerima parameter vararg (Jumlah argumen variabel) seperti:

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

Sekarang untuk memanggil metode ini, kita bisa melakukan:

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

Tetapi bagaimana jika kita memiliki nilai ini dalam sebuah array, seperti:

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

maka untuk memanggil metode ini kita harus menggunakan operator spread, seperti:

 sum(*array)

Di sini, * (operator penyebaran) akan meneruskan semua konten dari array itu.

* array setara dengan 1,2,3,4,5

Tapi tunggu sebentar, bagaimana jika kita menyebutnya seperti ini: sum(array) itu akan memberi kita kesalahan waktu kompilasi Type Mismatch:

Type mismatch.
Required:Int
Found:IntArray

Masalahnya adalah sumfungsi menerima vararg Intparameter (yang menerima nilai seperti: 1,2,3,4,5) dan jika kita melewatkan array, itu akan dilewatkan sebagai IntArray.

Suraj Vaishnav
sumber
5

Di Java, Anda dapat meneruskan array sebagaimana adanya, tetapi keuntungan dari membongkar array dengan operator spread *adalah operator spread memungkinkan Anda menggabungkan nilai dari array dan beberapa nilai tetap dalam satu panggilan. Java tidak mendukung ini.

Gulzar Bhat
sumber
1
Suara positif, karena saya bertanya pada diri sendiri mengapa mereka menerapkannya seperti ini. Saya masih belum 100% yakin tentang itu. Maksud saya, tidak bisakah mereka menyimpulkan ini dalam banyak kasus?
Tim Büthe
1
@ TimBüthe Dalam beberapa kasus, tidak mungkin untuk menyimpulkannya, pertimbangkan kasus berikut val resultOne = arrayOf(intArrayOne, intArrayTwo)dan val resultTwo = arrayOf(*intArrayOne, *intArrayTwo). Jenis resultOnedan resultTwomasing-masing adalah Array<Int>dan Array<Array<Int>>. Saya percaya itulah salah satu alasannya
Farid