• 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")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    调用方式如下:

    EVENT_ID.log()
    EVENT_ID.log("name", "小马快跑")
    EVENT_ID.log("name", "小马快跑", "city", "北京")
    
    • 1
    • 2
    • 3

    示例中可变参数可以是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, 北京]
    
    • 1
    • 2
    • 3

    可以看到通过定义可变参数,在调用方可以灵活地传入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)
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    转换之后:

     // 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));
             }
          }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 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

  • 相关阅读:
    [CC2642R1][VSCODE+Embedded IDE+Cortex-Debug] TI CC2642R1 快速搭建VsCode开发环境
    elements ui vue table 多选操作
    一步一步生成滑动验证码图片
    【前端】Vue+Element UI案例:通用后台管理系统-导航栏
    [攻防世界 XCTF 4th-WHCTF-2017] BABYRE
    终极大招~pycharm自动补全opencv代码提示功能
    在FreeSQL中实现「触发器」和软删除功能
    代码随想录算法训练营第23期day12| 239. 滑动窗口最大值 、347. 前K个高频元素
    优先级队列(priority_queue)
    ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-2-03:开发环境测试
  • 原文地址:https://blog.csdn.net/u013700502/article/details/127987833