Kotlin | 使用vararg可变参数

简介: kotlin中vararg的使用规则

背景

一般在项目开发中,我们经常会在关键节点上埋点,而且埋点中会增加一些额外参数,这些参数通常是成对出现参数个数是不固定的。如下:

//定义事件EVENT_ID
const val EVENT_ID = "event_xmkp"

//注意:这里传入的是vararg可变参数
fun String.log(vararg args: String) {
    if (args.size % 2 > 0) {
        throw RuntimeException("传入的参数必须是偶数")
    }
    if (args.isEmpty()) {
        buryPoint(this)
    } else {
        //注意这里:可变参数在作为数组传递时需要使用伸展(spread)操作符(在数组前面加 *)
        buryPoint(this, *args)
    }
 }

private fun buryPoint(eventId: String, vararg args: String) {
    if (args.isNotEmpty()) {
        Log.e(TAG, "buryPoint: $eventId, args: ${args.toList()}")
    } else {
        Log.e(TAG, "buryPoint: $eventId")
    }
}

调用方式如下:

EVENT_ID.log()
EVENT_ID.log("name", "小马快跑")
EVENT_ID.log("name", "小马快跑", "city", "北京")

示例中可变参数可以是0个、2个、4个,执行结果:

2022-11-22 19:00:54 E/TTT: eventID: event_xmkp
2022-11-22 19:00:54 E/TTT: eventID: event_xmkp, args: [name, 小马快跑]
2022-11-22 19:00:54 E/TTT: eventID: event_xmkp, args: [name, 小马快跑, city, 北京]

可以看到通过定义可变参数,在调用方可以灵活地传入0个多个参数,下面就分析下Kotlin方法中的可变参数。

注意:可变参数在作为数组传递时需要使用伸展操作符(在数组前面加 *),如果去掉 *号,编译器会报如下错:

请添加图片描述

Kotlin中使用可变参数

Java中可变参数规则:

  • 使用...表示可变参数
  • 可变参数只能在参数列表的最后
  • 可变参数在方法体中最终是以数组的形式访问

Kotlin中可变参数规则:

  • 不同于Java,在Kotlin中如果 vararg 可变参数不是列表中的最后一个参数, 可以使用具名参数语法传递其后的参数的值。
  • Java一样,在函数内,可以以数组的形式使用这个可变参数的形参变量,而如果需要传递可变参数,需要在前面加上伸展(spread)操作符(在数组前面加 *),第一节已给出示例。

对Kotlin可变参数反编译

对上一节中的String.log()代码反编译成Java代码:

//kt代码
fun String.log(vararg args: String) {
    if (args.size % 2 > 0) {
        throw RuntimeException("传入的参数必须是偶数")
    }
    if (args.isEmpty()) {
        buryPoint(this)
    } else {
        //注意这里:可变参数在作为数组传递时需要使用伸展(spread)操作符(在数组前面加 *)
        buryPoint(this, *args)
    }
 }

转换之后:

 // Java代码
 public final void log(@NotNull String $this$log, @NotNull String... args) {
      ...
      if (args.length % 2 > 0) {
         throw (Throwable)(new RuntimeException("传入的参数必须是偶数"));
      } else {
         if (args.length == 0) {
            this.buryPoint($this$log);
         } else {
            this.buryPoint($this$log, (String[])Arrays.copyOf(args, args.length));
         }
      }
 }
  • Kotlinvararg args: String参数转换成Java的 @NotNull String... args
  • Kotlinspread伸展操作符*args转换成Java(String[])Arrays.copyOf(args, args.length),可见最终还是通过系统拷贝生成了数组。

资料

【1】https://www.kotlincn.net/docs/reference/functions.html

相关文章
|
安全 Java 编译器
Kotlin | 理解泛型使用
泛型,指的是具体的类型泛化,多用在集合中(如`List`、`Map`),编码时使用符号代替,在使用时再确定具体类型。
126 0
|
Java 开发者 Kotlin
Kotlin中lambda表达式详解
lambda运算时java后面版本引进的,所以实现的仅仅是从形式上简化代码,内部的优化并不是非常出色,而Kotlin一开始就支持函数式编程,使得其lambda表达式具有性能上的优势,同时Kotlin简洁的风格也给lambda表达式进一步简化提供了一个良好的实现方式,下面带大家具体看看他们之间的区别以及如何更好的使用Kotlin的极简化lambda表达式
134 0
Kotlin中lambda表达式详解
|
安全 Java C#
Kotlin 之泛型详解
Kotlin 之泛型详解
|
编译器 Kotlin
Kotlin 之表达式详解
Kotlin 之表达式详解
|
存储 Java 编译器
Kotlin | 浅谈 Reified 与泛型 的三两事
背景 在业务中,或者要写某个技术组件时,我们无可避免会经常使用到 泛型 ,从而让代码更具复用性与健壮性。 但相应的,由于Java泛型存在 类型擦除 的实现机制,所以某些情况下就会显得力不从心。而在 Kotlin 中,由于最终也会被编译为java字节码,所以无可避免也存在这上述问题🙂。
180 0
|
安全 IDE Java
又被 Kotlin 语法糖坑惨的一天
又被 Kotlin 语法糖坑惨的一天
168 0
又被 Kotlin 语法糖坑惨的一天
|
安全 Java 编译器
kotlin泛型
kotlin泛型
129 0
|
JavaScript 前端开发 Java
浅谈Kotlin中的函数
本文简单谈下Kotlin中的函数,包括表达式函数体,命名参数,默认参数,顶层函数,扩展函数,局部函数,Lambda表达式,成员引用,with/apply函数等。从例子入手,从一般写法到使用特性进行简化,再到原理解析。
1113 0
|
Java API Kotlin
聊聊Kotlin中的lambda
聊聊Kotlin中的lambda
119 0
|
Java 编译器 Kotlin
聊聊Kotlin中的元编程
聊聊Kotlin中的元编程
277 0
聊聊Kotlin中的元编程