What am I doing wrong here?
fun main(args: Array<String> = arrayOf("abc")) {
val a = args[0]
}
compiles fine but:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
I want to make it optional to have an argument and supply a default value if none was specified
This probably does not work because of how the underlying Java platform works and how Kotlin translates default arguments to something the JVM can understand. You could say it's a bug in Kotlin...
The Java virtual machine looks for a method with the following signature to run your program (this is Java):
public static void main(String[] args)
Note that default argument values do not exist in Java, so if you declare a method with default values in Kotlin, the Kotlin compiler generates multiple methods in the Java byte code that will look like this when converted to 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" });
}
When you run the program, the JVM will still look for the method with the String[] args
argument. It will ignore the method with no arguments, that was generated for the Kotlin main
method with default arguments.
So it's always going to call the String[] args
version, even if there are no arguments on the command line - leading to the error that you get.
Workaround: Don't use default values for the main
method; check if arguments were given inside the method:
fun main(args: Array<String>) {
val realArgs = if (args.size > 0) args else arrayOf("abc")
// work with realArgs
}
I think it's a question of signature the JVM's search for main
methods: a main
method should have one parameter of String[]
type, and this parameter receives value(s) from CLI; if the CLI does not provide any parameter, the main
method receives a new String[0]
, which causes the error you're experiencing.
I think you can solve the problem slightly changing the approach:
fun main(args: Array<String>) {
println(args)
val a = args.getOrElse(0) {"abc"}
println(a)
}
should work for your scenario: if there is no parameter with index 0
a
gets the default value you passed (as a lambda) to getOrElse
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With