Home » Java » Why do I have to return Unit.INSTANCE in a void kotlin function, when called from Java, and not NULL?-Exceptionshub

Why do I have to return Unit.INSTANCE in a void kotlin function, when called from Java, and not NULL?-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

When having a function, for example:

fun doSomething(action:() -> Unit) {
   action.invoke()
}

if I call this from Java the code needs to be:

doSomething(() -> {
   //do something
   return Unit.INSTANCE
})

I have seen code instead using

doSomething(() -> {
   //do something
   return null
})

Does it affect sending null instead of Unit.INSTANCE? Do Kotlin perform more things by validating that UNIT instance is returned instead?

How to&Answers:

I think most of the time it will not really matter whether null or Unit.INSTANCE is used. However as there is at least 1 case where such a null is not desirable, you should probably always use Unit.INSTANCE then.

One such made-up example where not returning Unit.INSTANCE will cause a problem is the following:

fun doSomething(action:() -> Unit) {
   action.invoke() logReturnTime("after action invocation")
}
infix fun Unit.logReturnTime(msg : String) { TODO("logging return time $msg") }

If you would call this and return null you would get an IllegalArgumentException, whereas the code would run without problem if you use Unit.INSTANCE.

That having said, I don’t believe this is a good example, but it clearly shows, if anyone operates on that Unit, then it could fail, so you probably better always use Unit.INSTANCE and you are safe, regardless on what the receiver does with your function.

Answer:

Any method in Kotlin returns a value. “void” methods always return the one instance of the type Unit which is Unit.INSTANCE. You can obmit the return type unit in the declaration but implicitly it is added and the value is returned at the end of the method.
https://kotlinlang.org/docs/reference/basic-syntax.html

So when calling the Kotlin method from Java code, you need to fullfill the same contract and return something. If you return null is is a null reference to the type Unit. Just because it is better, to avoid null references, in case a caller would like to act on the result of your method, you should avoid returning null and return Unit.INSTANCE instead. Yes, this case is unlikely, but will cause the most annoying error.