Оператор звездочки Kotlin до имени переменной или оператора Spread в Котлине

Я хочу знать, что именно звездочка делает до имени переменной в Kotlin. Я видел это (*args) в Spring загрузите пример 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)
}

Ответ 1

Оператор * известен как оператор распространения в Kotlin.

Из Kotlin Reference...

Когда мы вызываем функцию vararg, мы можем передавать аргументы один за другим, например, asList (1, 2, 3) или, если у нас уже есть массив и мы хотим передать его содержимое в функцию, мы используем оператор распространения (префикс массива *):

Его можно применить к массиву перед передачей в функцию, которая принимает 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++, поскольку похоже, что указатель на него не ссылается. Это не так; Котлин не имеет представления об указателях.
  • Оператор может использоваться между другими аргументами при вызове функции vararg. Это продемонстрировано в примере здесь.
  • Оператор аналогичен функции apply в различных функциональных языках программирования.

Ответ 2

В дополнение к ответам, которые были непосредственно направлены на "что это за штука!?!", вы часто имеете случай, когда у вас есть List и хотите передать его функции, ожидающей vararg. Для этого преобразование:

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

Предполагая, что последний параметр someFunc равен vararg того же типа, что и элементы в списке.

Ответ 3

Как описано в документации, это оператор с расширением:

Когда мы вызываем vararg-функцию, мы можем передавать аргументы один за другим, например. asList (1, 2, 3), или, если мы уже имеем массив и хотим передать его содержимое функции, мы используем оператор спрединга (префикс массива с *):

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

Ответ 4

В Java вы можете передать массив как есть, но преимущество распаковки массива с оператором распространения * заключается в том, что оператор spread позволяет объединить значения из массива и некоторые фиксированные значения в одном вызове. Java не поддерживает это.

Ответ 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)

Здесь * (оператор распространения) пропустит все содержимое этого массива.

*array is equivalent to 1,2,3,4,5

Но подождите минутку, что если мы назовем это так: sum(array) это даст нам ошибку несоответствия типов:

Type mismatch.
Required:Int
Found:IntArray

Проблема в том, что функция sum принимает параметр vararg Int (который принимает значение, например: 1,2,3,4,5), и если мы передадим массив, он будет передан как IntArray.