138

I want to know what exactly an asterisk does before a variable name in Kotlin. I saw this (*args) in a Spring boot Kotlin example:

@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)
}
Paulo Merson
  • 11,433
  • 6
  • 73
  • 64
mojtab23
  • 2,263
  • 5
  • 19
  • 30

5 Answers5

232

The * operator is known as the Spread Operator in Kotlin.

From the Kotlin Reference...

When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):

It can be applied to an Array before passing it into a function that accepts varargs.

For Example...

If you have a function that accepts a varied number of arguments...

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

Use the spread operator to pass an array's elements as the arguments:

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

Notes:

  • The * operator is also the multiplication operator (of course).
  • The operator can only be used when passing arguments to a function. The result of the operation cannot be stored since it yields no value (it is purely syntactic sugar).
  • The operator may confuse some C/C++ programmers at first because it looks like a pointer is being de-referenced. It isn't; Kotlin has no notion of pointers.
  • The operator can be used in-between other arguments when calling a vararg function. This is demonstrated in the example here.
  • The operator is similar to the apply function in various functional programming languages.
byxor
  • 5,255
  • 4
  • 28
  • 43
  • 2
    Is Spread operator inline array? For example for array a = [1, 2, 3] funWithVararg(*a) inlines into funWithVararg(1,2,3)? I mean in bytecode level. – David May 27 '20 at 08:35
  • You may want to add to your list of notes, that it works exactly the same as in Python. – Sebi Aug 18 '21 at 06:12
  • `The operator can only be used when passing arguments to a function. ` helped me. Thanks! – LiuWenbin_NO. Apr 18 '22 at 02:39
31

In addition to the answers that were directly towards "what is this thing!?!", you often have the case where you have a List and want to pass it to a function that is expecting a vararg. For this, the conversion is:

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

Assuming that last parameter of someFunc is vararg of the same type as the elements in the list.

Jayson Minard
  • 83,247
  • 35
  • 176
  • 219
  • Thank you so much! This should be in the official docs under the spread operator section as something to watch out for when your spread operator is not working. – pleasedesktop Sep 07 '17 at 09:52
  • Thanks! Really helpfull. Wondering what is "Spread Operator" behind the scenes? Is just a way to get a varargs value? – Nicolas Jafelle Nov 14 '17 at 18:13
12

As described in the documentation this is a spread operator:

When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):

val a = arrayOf(1, 2, 3) 
val list = asList(-1, 0, *a, 4)
miensol
  • 36,699
  • 6
  • 110
  • 108
7

In Java you can pass an array as is but an advantage of unpacking an array with spread operator * is that spread operator lets you combine the values from an array and some fixed values in a single call. Java doesn't support this.

Gulzar Bhat
  • 1,135
  • 10
  • 13
  • 1
    Upvoted, because I asked myself why they implemented it like this. I'm still not 100% sure about it. I mean, couldn't they just infer this in most cases? – Tim Büthe Aug 24 '19 at 11:39
  • 1
    @TimBüthe In some cases, it wouldn't be possible to infer it, consider the following cases `val resultOne = arrayOf(intArrayOne, intArrayTwo)` and `val resultTwo = arrayOf(*intArrayOne, *intArrayTwo)`. Type of `resultOne` and `resultTwo` are respectively `Array` and `Array>`. I beleive that's one of the reasons – Farid Oct 02 '19 at 08:42
7

If a function which accept a vararg(Variable number of arguments) parameter like:

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

Now to call this method, we can do:

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

But what if we have these value in an array, like:

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

then, to call this method we have to use spread operator, like:

 sum(*array)

Here, *(spread operator) will pass all content of that array.

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

But wait a minute, what if we call it like this: sum(array) it will give us Type Mismatch compile time error:

Type mismatch.
Required:Int
Found:IntArray

The problem is sum function accept a vararg Int parameter(which accept value like: 1,2,3,4,5) and if we pass array, it will be passed as IntArray.

Suraj Vaishnav
  • 6,867
  • 3
  • 40
  • 43