Kotlin中可变参数

作者: JamFF | 来源:发表于2020-07-09 17:13 被阅读0次

    对比 Java 中的可变参数

    先看下 Java 的可变参数,用我们最熟悉的 main 函数

    public static void main(String... args) {
    }
    

    很多人可能都觉得不对啊,参数应该是数组啊

    public static void main(String[] args) {
    }
    

    其实上面两种写法是一样的,从 Java5 开始引入了可变参数(varargs)

    对应的 Kotlin 的代码,也是两种方式,参数为数组:

    fun main(args: Array<String>) {
    }
    

    参数为可变参数:

    fun main(vararg args: String) {
    }
    

    可变参数的本质

    和 Java 一样,可变参数的本质就是数组,我们来测试一下:

    fun main() {
        foo("1", "2", "3")
    }
    
    fun foo(vararg args: String) {
        println(args::class)
        println(args.contentToString())
        for (i in args.indices) {
            println(args[i])
        }
    }
    

    打印:

    class kotlin.Array
    val kotlin.reflect.KClass<T>.java: java.lang.Class<T>
    [1, 2, 3]
    1
    2
    3
    

    我们可以清晰的看到 args 的类型为数组类型,并且可以直接调用数组的方法。

    如果你的第一行打印结果是:
    class [Ljava.lang.String; (Kotlin reflection is not available)
    需要在 build.gradle 中添加依赖:
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

    准确的说 args 的类型是 Array<out String> 类型:

    fun main() {
        foo("1", "2", "3")
    }
    
    fun foo(vararg args: String) {
        bar(args)
    }
    
    fun bar(args: Array<out String>) {
        println(args.contentToString())
    }
    

    可变参数的传参

    我们再来改造一下 bar 函数的参数类型,看下可变参数的传参:

    fun main() {
        foo("1", "2", "3")
    }
    
    fun foo(vararg args: String) {
        bar(args)
    }
    
    fun bar(vararg args: String) {
        println(args.contentToString())
    }
    

    编译器提示类型不匹配,需要一个 String 类型的参数,而传入了数组类型。

    传参报错

    在 Java 中可变参数是可以直接传递,并且可以和数组相互转换传递:

    public static void main(String[] args) {
        foo("1", "2", "3");
    }
    
    private static void foo(String... args) {
        bar1(args);
        bar2(args);
    }
    
    private static void bar1(String... args) {
        System.out.println(Arrays.toString(args));
    }
    
    private static void bar2(String[] args) {
        bar1(args);
    }
    

    在 Kotlin 中如果想将数组类型传入到可变参数,就需要使用一个特定的符号 *

    fun main() {
        foo("1", "2", "3")
    }
    
    fun foo(vararg args: String) {
        bar1(*args)
        bar2(args)
    }
    
    fun bar1(vararg args: String) {
        println(args.contentToString())
    }
    
    fun bar2(args: Array<out String>) {
        bar1(*args)
    }
    

    总结

    我对 Kotlin 中d可变参数的理解是:

    1. 可变参数会在函数体中,自动转变为数组类型
    2. 数组类型不能作为参数,直接传递给可变参数
    3. 在数组类型前面添加 * ,可以传递给可变参数

    最后,我们可以反编译看下 Kotlin 中的 foo 函数,看看 * 到底做了什么:

    public static final void foo(@NotNull String... args) {
        bar1((String[]) Arrays.copyOf(args, args.length));
        bar2(args);
    }
    

    就是一个复制数组的操作,相比 Kotlin 还是 Java 做的更便捷,可以在数组和可变参数之间直接自由转换。

    相关文章

      网友评论

        本文标题:Kotlin中可变参数

        本文链接:https://www.haomeiwen.com/subject/qxuuqktx.html