Kotlin中可變參數

對比 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 做的更便捷,可以在數組和可變參數之間直接自由轉換。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章