Can't Array<String> be passed to Array<String?> parameter?


#1

I'm using the latest build on the build server and have a very simple problem I can't seem to figure out.

I have a main function:

fun main(args: Array<String>) {   Application.launch(*args) }

I’m calling the launch method of the JavaFX Application class which seem to be expecting a varargs String?. The IDE gives me an error that no function can be found. I’ve attached a screenshot of the code and error.

I can’t change the args parameter to be Array<String?> because it can’t be executed as a program.

How can I call this launch function?

Curtis



Screen Shot 2013-01-26 at 8.46.34 PM.png (45.6 KB)

#2

So this is disallowed by Kotlin ... and for good reason. The problem is that Array is mutable ... consider the following example:

fun foo(stuff: Array<String?>) {   stuff[0] = null;   // perfectly legal, since stuff is : Array<String?> }

fun bar() {
  val args: Array<String> = array(“First”, “Second”, “Third”)
  foo(args)           // this isn’t legal but we’ll pretend it is …
  val thing: String = args[0]
  println(thing.length) // What Null pointer exception!! but thing isn’t nullable!!
}

Best way to solve this in your case is probably just to make a copy …

fun main(args: Array<String>) {   val copy = Array<String?>(args.size, { i -> args[i] })   Application.launch(*copy) }


#3

There's a difference though.

if you have a java method:

void foo(String[] stuff) {

  …


}

and you know that it doesn’t mutate the array, you should be able to change its kotlin signature with anotations from:

fun foo(Array<jet.String?>?)

to:

fun foo(Array<out jet.String?>?)

(I haven’t tried it, but I think that should work).

And then you should be able to give it your Array<String> without making any copy.

Now if foo uses a vararg:

void foo(String… stuff) {

  …


}

Its kotlin signature becomes:

fun foo(vararg jet.String?)

and I don’t know that you can change its signature to make it accept the Array<String>.


#4

Indeed, sadly you can't say

``

fun foo(vararg args: out String?) { … }   

Although logically it should be possible … Kotlin should probably allow ‘out’ in the case of vararg parameters.


#5

Yes, of course. I didn't think about the mutability aspect. Thanks for that and the code to convert it. I wasn't having any luck with that.