4

I have the following code in Java:

  public static void main(String[] args) {
    checkVarargs(null);
  }

  public static void checkVarargs(String... o) {
    System.out.println(o);
  }

When I try to auto-convert the main method to Kotlin I get the following:

    @JvmStatic
    fun main(args: Array<String>) {
      checkVarargs(null)
    }

However, In the Java case a null array is passed, and it prints null while on Kotlin case it prints [Ljava.lang.String;@548c4f57 (array that contains null).

Is it possible to pass null array to Java varargs from Kotlin code?

2
  • Possible duplicate: stackoverflow.com/questions/17667573/… Or at least the answer gives insight into why Commented Jun 27, 2019 at 12:20
  • 1
    In the Kotlin case it isn't an empty array, it's an array containing a single null. Commented Jun 27, 2019 at 16:36

2 Answers 2

4

The question is, why does Java behave like this? Does it make sense? Don't you want to pass a null String rather? Kotlin doesn't support this vague concept of "nullable varargs", you cannot achieve it as you could in Java.

checkVarargs() will pass an empty array

checkVarargs(null) will pass an array with null in it

Sign up to request clarification or add additional context in comments.

2 Comments

The only reason I want to do it is that I have code in Java and tests in Kotlin and I want to make sure this edge case is covered. If it's not possible I will write this test in Java.
I tried using the spread operator checkVarargs(*(null as Array<String>?)) but it gives "The spread operator (*foo) may not be applied to an argument of nullable type". So it does seem to be impossible.
0

trying to uses (not works)

@Suppress("SPREAD_OF_NULLABLE")
checkVarargs(*null) // still fails with NullPointerException

another (this works)

val checkVarargsNullable: (Array<String>?) -> Unit = ::checkVarargs
checkVarargsNullable(null) // test passed

and we can make a helper function to make it easier

@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <T : Any?, R> varargCallNull(noinline method: (Array<T>) -> R) = (method as (Any?) -> R)(null)

varargCallNull(::checkVarargs) // bingo

this only works for method references, not works for lambdas

varargCallNull { checkVarargs(it) } // compile error
varargCallNull { checkVarargs(*it) } // NullPointerException

so maybe we need more workarounds for multiple args vararg methods

@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <X, T : Any?, R> varargCallNull(noinline method: (X, Array<T>) -> R, x: X) = (method as (X, Any?) -> R)(x, null)

@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <X, Y, T : Any?, R> varargCallNull(noinline method: (X, Y, Array<T>) -> R, x: X, y: Y) = (method as (X, Y, Any?) -> R)(x, y, null)
// ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.