End

Java 及 Kotlin 中的可变参数 vararg

本文地址


目录

Java 及 Kotlin 中的可变参数 vararg

Java 中可变参数的规则

  • 可变参数只能出现在参数列表的最后
  • ... 代表可变参数,... 位于变量类型和变量名之间
  • 在方法体中以数组的形式访问可变参数

Kotlin 中的规则类似

可变参数的本质是数组

Java 中对应数组 T[]

public static void hello(String[] array, String... args) {
    Class<?> stringArrayClass = Array.newInstance(String.class, 0).getClass(); // 获取数组的 Class

    System.out.println(array.getClass() == args.getClass()); // true
    System.out.println(array.getClass() == stringArrayClass); // true
    System.out.println(args.getClass().getName()); // [Ljava.lang.String;
}

上面代码中的 stringArrayClass 代表的就是 String 数组的 Class 对象,参考

Kotlin 中可能对应 Array

fun hello(array: Array<String>, vararg args: String) {
    val stringArrayClass: Class<*> = java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass

    println(array.javaClass == args.javaClass) // true
    println(array.javaClass == stringArrayClass) // true
    println(args.javaClass.name) // [Ljava.lang.String;
}

或 IntArray 等衍生数组

fun hello(array: IntArray, vararg args: Int) {
    val intPrimitiveType: Class<Int>? = Int::class.javaPrimitiveType
    val intArrayClass: Class<*> = java.lang.reflect.Array.newInstance(intPrimitiveType, 0).javaClass

    println(array.javaClass == args.javaClass) // true
    println(array.javaClass == intArrayClass) // true
    println(args.javaClass.name) // [I
}

可变参数的应用

可变参数的声明

public static void javaTest(String name, int... args) {
    System.out.println(name + " -- " + args.length);
}
fun kotlinTest(name: String, vararg args: Int) = println("$name - ${args.size}")

可变参数是否可为空

  • Java 中可变参数可为空,所以在调用前必须判空
  • Kotlin 中可变参数不可为空,所以在调用前不需要判空
    • 如果判空了,IDE 会提示你:Condition 'args==null' is always 'false'
    • 在 Java 中调用 Kotlin 的可变参数时,虽然传 null 可以编译通过,但运行时会直接崩溃
javaTest("bqt");                // bqt - 0
javaTest("bqt", null);          // 编译通过,运行时崩溃
MainKt.kotlinTest("bqt", null); // 编译通过,运行时会直接崩溃
kotlinTest("bqt")       // bqt - 0
kotlinTest("bqt", null) // 编译不通过,Null can not be a value of a non-null type Int
javaTest("bqt", null)   // 编译不通过,Null can not be a value of a non-null type Int

可变参数的调用

在 Kotlin 中,如果想将数组传入到可变参数,需要在引用前面加上 *

public static void javaTest(String name, int... args) {
    MainKt.kotlinTest(name, 1, 2); // 这里的 MainKt 是自动生成的一个类,用于封装 Kotlin 中的顶层函数
    MainKt.kotlinTest(name, args);
    MainKt.kotlinTest(name, new int[]{1, 2, 3});
}

Java 中调用 Kotlin 中定义的顶层函数时,需要以静态方法的语法去调用,类名是 Kotlin 文件名 + 后缀 Kt

fun kotlinTest(name: String, vararg args: Int) {
    Test.javaTest(name, 1, 2, 3)
    Test.javaTest(name, *args)
    Test.javaTest(name, *IntArray(3)) // 这里的 3 代表的其实是 size
}

Kotlin 类型转换

fun main() {
    intTest("IntArray", *intArrayOf(1, 2, 3)) // Remove redundant spread operator
    intTest("Array<Int>", *arrayOf(1, 2, 3).toIntArray())
    intTest("List<Int>", *listOf(1, 2, 3).toIntArray())

    val stringArray = com.sun.xml.internal.fastinfoset.util.StringArray().also { it.add("1") }
    stringTest("StringArray", *stringArray.array)
    stringTest("Array<String>", *arrayOf("2")) // Remove redundant spread operator
    stringTest("List<String>", *listOf("3").toTypedArray())
}

fun intTest(name: String, vararg args: Int) = println("$name - ${args.toList()}")
fun stringTest(name: String, vararg args: String) = println("$name - ${args.toList()}")

StringArray 并不是 Kotlin 中定义的类,而是一个 Java 类。继承自 ValueArray(继承自 Object)
StringArray.array 其实是调用了 public String[] getArray() 方法

2022-5-2

posted @ 2022-05-02 19:38  白乾涛  阅读(2075)  评论(2编辑  收藏  举报