1. 简介
我们知道,在 Kotlin 中可以使用 vararg
关键字来定义一个方法参数,表示该参数可以接收多个值。例如:
fun printStrings(vararg strings: String) {
strings.forEach(::println)
}
调用时可以直接传多个字符串:
printStrings("a", "b", "c")
但如果我们已经有了一个数组,比如 val arr = arrayOf("a", "b", "c")
,直接传入数组是不行的,因为函数期望的是一个个单独的参数,而不是一个数组。
那么,如何将一个数组转换成 vararg
参数传递给函数呢?这就是本文要解决的问题。
2. 使用 Spread 运算符(*)
Kotlin 提供了 spread 运算符(*),可以将数组“展开”为一个个单独的元素,从而适配 vararg
参数。
2.1. 基本用法
我们来看一个例子:
private fun concat(vararg strings: String): String {
return strings.fold("") { acc, next -> "$acc$next" }
}
这个函数接收多个字符串并拼接起来。
✅ 正确用法如下:
val strings = arrayOf("ab", "cd")
assertTrue { concat(*strings) == "abcd" }
⚠️ 注意:
- 只能使用 类型数组(typed array),比如
Array<String>
或arrayOf("a", "b")
- 如果是
List
,需要先转换为数组:
val listOfStrings = listOf("ab", "cd")
assertTrue { concat(*listOfStrings.toTypedArray()) == "abcd" }
2.2. 参数顺序问题
和 Java 不同,Kotlin 允许 vararg 参数出现在任意位置,不一定要放在最后。
但这样会带来一个问题:如果 vararg
不是最后一个参数,调用时可能无法自动识别后续参数。
解决办法有两个:
- 给非
vararg
参数设置默认值 - 使用命名参数调用函数
举个例子:
private fun concat2(vararg strings: String, initialValue: String = "01"): String {
return strings.fold(initialValue) { acc, next -> "$acc$next" }
}
private fun concat3(vararg strings: String, initialValue: String): String {
return strings.fold(initialValue) { acc, next -> "$acc$next" }
}
调用方式如下:
assertTrue { concat2(*strings) == "01abcd" }
assertTrue { concat3(strings = *strings, initialValue = "01") == "01abcd" }
可以看到,concat3
中没有默认值,所以必须使用命名参数明确传参。
2.3. 多个 Spread 操作合并使用
虽然 Kotlin 中一个函数只能有一个 vararg
参数,但我们可以传入多个数组,甚至混合字面量与数组:
val strings = arrayOf("ab", "cd")
val moreStrings = arrayOf("ef", "ghij")
assertTrue { concat(*strings, "kl", *moreStrings) == "abcdefghij" }
✅ 这种写法非常灵活,适用于需要合并多个数组或集合的情况。
3. 总结
在 Kotlin 中,将数组转换为 vararg
参数的核心方式是使用 spread 运算符(*)。主要用法包括:
- ✅ 使用
*array
传递数组 - ✅ 将
List
转换为toTypedArray()
后再使用 spread - ✅ 支持在任意位置放置
vararg
参数(需注意参数顺序问题) - ✅ 可以合并多个数组或字面量一起传入
这些技巧在处理 Kotlin 与 Java 的互操作、构建灵活的函数接口时非常实用。
完整代码示例可在 GitHub 上找到。