對比 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可變參數的理解是:
- 可變參數會在函數體中,自動轉變爲數組類型
- 數組類型不能作爲參數,直接傳遞給可變參數
- 在數組類型前面添加
*
,可以傳遞給可變參數
最後,我們可以反編譯看下 Kotlin 中的 foo 函數,看看 *
到底做了什麼:
public static final void foo(@NotNull String... args) {
bar1((String[]) Arrays.copyOf(args, args.length));
bar2(args);
}
就是一個複製數組的操作,相比 Kotlin 還是 Java 做的更便捷,可以在數組和可變參數之間直接自由轉換。