为main指定默认参数

时间:2019-02-20 14:00:25

标签: kotlin

我在这里做什么错了?

fun main(args: Array<String> = arrayOf("abc")) {
    val a = args[0]
}

编译正常,但是:

  

线程“ main”中的异常java.lang.ArrayIndexOutOfBoundsException:0

我想使其具有参数作为可选参数,并在未指定参数的情况下提供默认值

2 个答案:

答案 0 :(得分:8)

由于底层Java平台的工作方式以及Kotlin如何将默认参数转换为JVM可以理解的内容,因此这可能行不通。您可以说这是Kotlin中的错误...

Java虚拟机正在寻找一种具有以下签名的方法来运行程序(这是Java):

public static void main(String[] args)

请注意,默认参数值在Java中不存在,因此,如果在Kotlin中声明具有默认值的方法,则Kotlin编译器会在Java字节码中生成多个方法,这些方法在转换为Java时将如下所示:

public static void main(String[] args) {
    // the normal main method
}

// generated because you have a method with default values
public static void main() {
    main(new String[]{ "abc" });
}

运行程序时,JVM仍将寻找带有String[] args参数的方法。它将忽略不带参数的方法,该方法是为带有默认参数的Kotlin main方法生成的。

因此,即使命令行上没有任何参数,也总是要调用String[] args版本-导致出现错误。

解决方法:不要对main方法使用默认值;检查参数是否在方法内部给出:

fun main(args: Array<String>) {
    val realArgs = if (args.size > 0) args else arrayOf("abc")

    // work with realArgs
}

答案 1 :(得分:3)

我认为这是JVM搜索main方法的签名问题:main方法应具有一个String[]类型的参数,并且此参数从CLI接收值;如果CLI不提供任何参数,则main方法将收到new String[0],这将导致您遇到错误。

我认为您可以通过稍微改变方法来解决问题:

fun main(args: Array<String>) {
    println(args)
    val a = args.getOrElse(0) {"abc"}
    println(a)
}

适用于您的情况:如果没有索引为0的参数,则a获得您传递给getOrElse的默认值(作为lambda)。