编程Kotlin 开发者

'vararg' 在 Kotlin 中如何工作?描述传递规则、限制、与常见模式的交互及与命名和常规参数组合时的典型问题。

用 Hintsage AI 助手通过面试

答案。

Kotlin 中的关键字 vararg 允许函数接收可变数量的参数。这相当于 Java 中的数组,但带有额外的语法糖。

规则和限制:

  • 一般语法:fun foo(vararg numbers: Int)
  • vararg 参数必须是函数参数中的最后一个(如果后面有参数,则在调用时必须使用命名参数)。
  • 可以传递单个值,也可以传递数组(使用展开运算符 *)。
  • 可以在不传递该参数值的情况下调用带有 vararg 的函数。

代码示例

fun printAll(vararg strings: String) { for (s in strings) println(s) } val arr = arrayOf("a", "b", "c") printAll("one", "two") // 可以工作 printAll(*arr) // 展开(解压数组)

设问。

可以在一个函数中声明两个 'vararg' 参数,或者将 'vararg' 放在最后一个参数之前吗?

答案:不可以,在 Kotlin 中,一个函数声明中只能使用一个 vararg,并且它必须始终是位置参数中的最后一个。如果在它之后添加常规参数,则只能按名称传递。

示例:

fun foo(vararg items: String, prefix: String) // 编译错误! // 正确: fun foo(vararg items: String, vararg items2: Int) // 编译错误! // 可以工作: fun foo(vararg items: String, prefix: String = "[default]") foo("a", "b", prefix = "->")

由于对主题细节不了解而导致的真实错误示例。


故事

一位年轻程序员错误地认为可以同时声明两个 vararg 参数。函数架构是以多级调用为基础的。这导致了一系列重构——不得不重新考虑接收数据的逻辑并重写所有调用。


故事

在一个 Android 项目中,忘记在将数组传递给带有 vararg 参数的函数时使用展开运算符 *printAll(arr) 而不是 printAll(*arr)。结果,元素被输出为一个字符串,显示为对象地址,导致应用程序逻辑行为异常。


故事

在一个带有 vararg 和附加命名参数的函数 fun foo(vararg a: Int, b: Int) 中,通过位置参数的调用被错误地解释:编译器无法确定 vararg 的结束位置和参数 b 的开始位置,导致编译错误。决定为此类参数明确使用参数名称。