I have a java function:
public static void initialize(@NonNull Activity activity, Settings... settings) {}
I want to call it from kotlin:
fun initialize(activity: Activity, vararg settings: settings) = JavaClass.initialize(activity, settings)
But it does not compile, telling me that there is type mismatch, Settings
is required, but the argument is kotlin.Array<out Settings>
I see that it's trying to match it with signture
public static void initialize(@NonNull Activity activity, Settings settings) {}
but I want to use
public static void initialize(@NonNull Activity activity, Settings[] settings) {}
You should use the following syntax:
fun initialize(activity: Activity, vararg settings: settings) =
JavaClass.initialize(activity, *settings)
https://kotlinlang.org/docs/reference/java-interop.html#java-varargs
Michael's answer is correct, though I'd like to make some additional comments.
The reason you cannot pass a Kotlin vararg
parameter into a Java (or Kotlin) function that expects another vararg
is because the compiler resolves the vararg
into an Array
.
Hence, it is as if you've declared your function as below (from the perspective of the function's internal scope):
fun initialize(activity: Activity, settings: Array<Settings>) = //...
This is why it is unintuitive that we need to use the spread *
operator. As far as I can tell, there are two benefits to this design choice:
The spread operator, in addition to being used to populate variable arguments, can be used to mix-and-match between individual arguments and spreaded arrays. This means that Kotlin is giving us a convenient way to add additional parameters to a vararg
list.
In Java, the following code does not compile:
Settings[] settings = //...
Setting myAdditionalSetting = new Setting();
JavaClass.initialize(activity, settings, myAdditionalSetting); //Compiler Error
However, in Kotlin we can do this:
JavaClass.initialize(activity, *settings, myAdditionalSetting)
The second benefit is increased safety. The spread operator compiles down to a call to Arrays.copyOf()
which guarantees immutability of the spreaded values.i This ensures that the called function cannot corrupt the original array.
i: While the actual class references would be immutable, the objects they refer to might still be mutable.