Kotlin 使用vararg可变参数
Posted -小马快跑-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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));
Kotlin
的vararg args: String
参数转换成Java的@NotNull String... args
Kotlin
的spread
伸展操作符*args
转换成Java
的(String[])Arrays.copyOf(args, args.length)
,可见最终还是通过系统拷贝生成了数组。
资料
【1】https://www.kotlincn.net/docs/reference/functions.html
关于可变参数varargs
今天在看源码的时候,面对以下有点蒙蔽,在这里对可变参数做一下总结。
主要理解取自一个博客,c版本的:https://www.cnblogs.com/bettercoder/p/3488299.html
示例输出如下:
更多详细解释请看: http://www.cplusplus.com/reference/cstdarg/va_arg/?kw=va_arg
c++中的TMP:
主要参考c++primer page:618-624 (当时觉得应该用不上这么魔幻的操作就跳过了 QAQ)
术语:
可变数目的目的参数被称为参数包(parameter packet)
模板参数包(template parameter packet)
函数参数包(function parameter packet)
template <typename T,typename... Args> void foo(const T& t, const Args& ... rest) { std::cout << sizeof...(Args) << endl; std::cout << sizeof...(rest) << endl; } int main() { foo(1, 2, 3, 4, 5, 6, 7, 8); system("pause"); return 0; }
都输出了7。
更高级的std::forward保证了模板传参时原来是右值的参数仍为右值,而不会变成左值。
详细如下:http://www.cplusplus.com/reference/utility/forward/?kw=forward
以上是关于Kotlin 使用vararg可变参数的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin泛型总结 ★ ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 | 可变参数结合泛型 | out 协变 | in 逆变 | reified 检查泛型参数类型 )
Kotlin vararg:如何将 null 设置为不抛出 NullPointerException 的 vararg?