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 上找到。


原始标题:Convert Kotlin Array to Varargs