175

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)
}
0

5 Answers 5

297

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

From the Kotlin Reference:

When you call a vararg-function, you can pass arguments individually, for example asList(1, 2, 3). if you already have an array and want to pass its contents to the function, use the spread operator (prefix the array with *):

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

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.
Sign up to request clarification or add additional context in comments.

4 Comments

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.
You may want to add to your list of notes, that it works exactly the same as in Python.
The operator can only be used when passing arguments to a function. helped me. Thanks!
"The operator can be used in-between other arguments when calling a vararg-function. This is demonstrated in the example here." Not exactly! The example shows only a list of all ints, all just one vararg. "Only one parameter can be marked as vararg. If a vararg parameter is not the last one in the list, values for the subsequent parameters can be passed using named argument syntax, or, if the parameter has a function type, by passing a lambda outside the parentheses." Of course, in the cited example, 4 is not passed as a named argument...
39

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.

3 Comments

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.
Thanks! Really helpfull. Wondering what is "Spread Operator" behind the scenes? Is just a way to get a varargs value?
Actually, you're not passing a List, it only works for arrays; that's why -in your example- you have to convert it.
13

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)

Comments

9

Consider a function which accepts a vararg (Variable number of arguments) parameter like below:

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

We can call this method with

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

But if we have these same values in an array, like:

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

Then, we can call this method using the spread operator, like:

sum(*array)

Here, *(spread operator) will pass all the content of the array to the function.

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

But a call like this:

sum(array)

will give us Type Mismatch compile time error:

Type mismatch.
Required:Int
Found:IntArray

This is because the array sum(array) will be passed as IntArray, but this call sum(*array) will pass the contents of the array to the function.

Comments

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.

2 Comments

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?
@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<Int> and Array<Array<Int>>. I beleive that's one of the reasons

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.