ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### [可变参数](http://www.kotlincn.net/docs/reference/functions.html#%E5%8F%AF%E5%8F%98%E6%95%B0%E9%87%8F%E7%9A%84%E5%8F%82%E6%95%B0varargs):vararg关键字 [TOC] #### 可变参数的定义和示例 什么是可变参数?适用于参数个数不确定,类型确定的情况。可变参数通过vararg关键字标识,我们可以将其理解为数组。 **Kotlin把可变参数当做数组处理**。可变参数通常声明在形参列表中的最后位置,如果不声明在最后位置,那么可变参数后面的其他参数都需要通过命名参数的形式进行传递。 **Kotlin的可变参数通过vararg关键字实现**。参考代码: ~~~ fun main(args: Array<String>) { myFun(1, "a", "b", "c") } fun myFun(x: Int, vararg y: String) { println("x:$x") println("y:$y") println("y.size:${y.size}") println("--------可变参数,可以遍历---------") for (s in y) { println(s) } } ~~~ 运行结果 ``` x:1 y:[Ljava.lang.String;@5e2de80c y.size:3 --------可变参数,可以遍历--------- a b c Process finished with exit code 0 ``` 针对以上代码我们可以看到,**被vararg修饰的变量,有size属性,可以进行遍历**。 * 示例 ``` fun sum(name:String,vararg scores: Int){ var result = 0 scores.forEach { result += it } println("江小白的总成绩:" + result) } fun main(args: Array<String>) { sum("江小白", 100, 99, 98, 100, 96) } ``` 运行结果 ``` 江小白的总成绩:493 ``` 在上述代码中,声明了一个sum()函数用于求总成绩,在该函数中传递了一个String类型的参数name与一个可变参数scores。由于可变参数可以当作数组处理,因此可以使用forEach循环遍历scores中的值,循环中的it表示每次遍历scores中的元素,然后将这些元素累加并赋值给result,输出总成绩。当在main()方法中调用sum()函数时,需要传递一个String类型的实参,以及任意多个Int类型数据,即可得出某人的总成绩。 **由于可变参数实质上就是数组,因此,可以直接使用数组存放可变参数,在传递时使用数组即可,这样更加直观方便**。具体示例代码如下: ``` var scores: IntArray = intArrayOf(100, 99, 98, 100, 96) sum("江小白", * scores) ``` >[success]需要注意的是,在实参中传递数组时,需要使用“*”前缀操作符,意思是将数组展开,它只能展开数组,不能展开集合。 可变参数相对来说比较复杂,当可变参数不在形参列表中的最后位置时,其他形参该如何通过命名参数进行传递呢? ``` fun sum(vararg scores: Int, name: String){ var result = 0 scores.forEach { result += it } println("江小白的总成绩:" + result) } fun main(args: Array<String>) { sum(100, 99, 98, 100, 96, name = "江小白") } ``` #### **可变参数只能出现在参数列表的最后???** 接收我们编写一个方法,测试一下**可变参数只能出现在参数列表的最后**这个结论,参考代码: ![](https://box.kancloud.cn/4c2d22a9e2a54345f02e077cfa9ddd83_681x241.png) 通过以上代码,我们验证了“**可变参数只能出现在参数列表的最后**”。 **如果vararg标记的参数不是最后一个参数,需要用[命名参数]传递其之后的参数,或者,如果参数具有函数类型,则通过在括号外部传⼀个 lambda。** ~~~ fun <T> asList(vararg ts: T, name: String){ for (t in ts) print("$t,") print(name) } fun main(args: Array<String>) { asList(1,2,3,name="lioil.win")//输出1,2,3,lioil.win } ~~~ 当我们调用`vararg`-函数时,我们可以一个接一个地传参,例如`asList(1, 2, 3)`,或者,如果我们已经有一个数组并希望将其内容传给该函数,我们使用**伸展(spread)操作符**(在数组前面加`*`): ``` fun <T> asList(vararg ts: T): List<T> { val result = ArrayList<T>() for (t in ts) // ts is an Array result.add(t) return result } val a = arrayOf(1, 2, 3) val list = asList(-1, 0, *a, 4) ``` #### Kotlin中的可变参数与Java中的可变参数的对比 * [ ] **Kotlin中可变参数规则:** * 可变参数可以出现在参数列表的任意位置; * 可变参数是通过关键字vararg来修饰; * 可以以数组的形式使用可变参数的形参变量,实参中传递数组时,需要使用“*”前缀操作符。 * [ ] **Java中可变参数规则:** * 可变参数只能出现在参数列表的最后; * 用“…”代表可变参数,“…”位于变量类型与变量名称之间; * 调用含有可变参数的函数时,编译器为该可变参数隐式创建一个数组,在函数体中以数组的形式访问可变参数。 可变参数的特点是参数个数不确定,类型确定的参数。Kotlin中把可变参数当作数组处理。 ``` fun add(vararg arr: Int): Int { var sum = 0 //定义一个变量sum arr.forEach { //对可变参数进行遍历 sum += it //每循环一次会加上可变参数arr中的值 } /*arr.forEachIndexed { index, i -> println("角标=$index 元素=$i") //打印数组中的角标和元素 }*/ return sum //循环结束,返回参数值的和 } fun main(args: Array<String>) { var result = add(1, 2, 3) //调用add()函数,并把该函数的返回值赋给变量result println(result) //打印变量result } ``` 运行结果 ``` 6 ``` 在上述代码中,通过fun关键字声明了一个函数add(),在这个函数中传递了一个可变参数arr,该可变参数由关键字vararg来修饰,同时该可变参数的类型指定为Int。由于可变参数本质上是一个数组,因此可变参数可以通过forEach()循环进行遍历。在forEach()函数中,it表示每次遍历的可变参数arr中的元素,每循环一次都会加上it的值,加完之后将最终的值赋给变量sum。在main()函数中调用add()函数,并向该函数传递3个Int类型的数据,分别是1、2、3,这3个数据会以数组的形式存放在可变参数arr中,在这里传递的数据的个数是任意的。接着将add()函数的返回值赋给变量result,最后打印变量result。