Categories
Kotlin

Kotlin: Concatenating nullable strings

A null String is concatenated as “null” in Kotlin:

val first:String? = "first"
val second:String? = null

println("First is $first and second is $second")
> First is first and second is null

What if the goal is to concatenate only if the second string is not null? There are a few options:

if-else

One of the solutions would be to check the null value with elvis(?:) operator:

var result = "First is ${(first ?: "")} and second is ${(second ?: "")}"
println("$result")
> First is first and second is 

Now there is no “null”, but the whole “and second is” part is superfluous because the second string has no value. With an if case this segment can be omitted completely:

result = 
(if (first != null) "First is $first" else "") +
(if (second != null) " and second is $second" else "")
> First is first

This is the desired result, but the code is not easy to read with double if checks and concatenation of empty string “”. What if we could hide this logic with an extension function?

Extension function with lambda expression

Using an extension function with a function parameter enables us to separate the if case logic:

fun String.concatIfNotNull(fromObject: Any?, transform: (String) -> String) =
  if (fromObject != null) this + transform(this) else this

result = "".concatIfNotNull(first) {
  "First is $first".concatIfNotNull(second) { " and second is $second" }
}
> First is first

This code doesn’t have the if cases, but one might argue it is even harder to read than the first solution because of the extension’s dot notation and empty string “” concatenation in the beginning.

Top-level function with lambda expression

By defining a top-level function we don’t have to use the dot notation and extra string concatenation:

inline fun <T> ifNotNull(fromObject: T?, transform: (T) -> String): String =
 if (fromObject != null) "" + transform(fromObject) else ""

result = ifNotNull(first) {
  "First is $first" + ifNotNull(second) { " and second is $second" }
}

This solution could seem like the most human-readable way of conveying the purpose of our code: appending a sentence only if its contents are not null.

Conclusion

Kotlin string literals can become difficult to read if multiple if cases are used to construct them.

The developer can be aware of this and use alternatives like top-level functions or extension functions. This can make the code more self-documenting and easier to read.