变量名前的Kotlin星号运算符或Kotlin中的Spread运算符


97

我想知道在Kotlin中变量名之前星号到底是做什么的。我*argsSpring 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)
}

Answers:


161

*运算在Kotlin中被称为Spread运算符

Kotlin参考 ...

当我们调用vararg函数时,我们可以一个一个地传递参数,例如asList(1、2、3),或者,如果我们已经有一个数组并且想要将其内容传递给函数,则可以使用运算符(在数组前面加上*):

可以在将其传递给accept的函数之前将其应用于Array 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 ++程序员感到困惑,因为看起来好像已取消引用了指针。不是 Kotlin 没有指针的概念
  • 调用vararg函数时,可以在其他参数之间使用运算符。这在此处的示例中得到了证明。
  • 该运算符类似于apply各种功能编程语言中的功能。

是Spread运算符内联数组吗?例如,对于数组a = [1、2、3] funWithVararg(* a)内联到funWithVararg(1,2,3)中?我的意思是字节码级别。
David

22

除了直接针对“这是什么!!!”的答案外,您通常还会遇到这样的情况,即您List希望将a传递给期望a的函数vararg。为此,转换为:

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

假设该最后一个参数someFuncvararg相同的类型在列表中的元素。


非常感谢!这应该在价差运算符部分下的官方文档中,作为您的价差运算符不工作时要注意的事项。

谢谢!真的很有帮助。想知道幕后的“散布算子”是什么?仅是一种获取varargs值的方法吗?
Nicolas Jafelle

11

文档中所述,这是一个传播算子:

当我们调用vararg函数时,我们可以一个一个地传递参数,例如asList(1、2、3),或者,如果我们已经有一个数组并且想要将其内容传递给函数,则可以使用运算符(在数组前面加上*):

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

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)

在这里,*(spread operator)将传递该数组的所有内容。

*数组等于1,2,3,4,5

但是请稍等,如果我们这样称呼它:sum(array) 它将给我们带来Type Mismatch编译时间错误:

Type mismatch.
Required:Int
Found:IntArray

问题是sum函数接受一个vararg Int参数(接受值,如:1,2,3,4,5),如果我们传递数组,它将作为传递IntArray


4

在Java中,您可以按原样传递数组,但是使用Spread运算符解压缩数组的好处*是,Spread运算符使您可以在单个调用中组合数组中的值和一些固定值。Java不支持此功能。


表示支持,因为我问自己为什么要这样实施。我仍然不确定100%。我的意思是,在大多数情况下他们难道不能只是推断吗?
蒂姆·布斯(TimBüthe)

1
@TimBüthe在某些情况下,无法推断出来,请考虑以下情况,val resultOne = arrayOf(intArrayOne, intArrayTwo)然后val resultTwo = arrayOf(*intArrayOne, *intArrayTwo)。类型resultOneresultTwo分别为Array<Int>Array<Array<Int>>。我相信这是原因之一
Farid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.