Kotlin: coding discussion: elegant way to check multiple variables which could null
Asked Answered
P

2

11

I use Kotlin to Programm Android Apps. For null-pointer safety one needs to check if all references are non-null. However if only one is null then we should inform the user that something went wrong.

It is important for me to program in a concise readable manner.

I am looking for a short and easy understandable solution.

The standard way would be:

if  (b != null && a != null && c !=null ...) println ("everything ok.")
else println("Something went wrong")
Pour answered 7/10, 2018 at 14:15 Comment(3)
Possible duplicate of Kotlin call function only if all arguments are not nullTrackman
Although this is a great question, unfortunately it's not a very good fit for StackOverflow, since it's primarily opinion-based. I would suggest you open a discussion at kotlinlang.slack.com, I'm sure you'll get good answers there.Inappropriate
Thank you, I will open a discussion at kotlinlang.slack.comPour
U
16

Here are two concise ways to write the condition:

listOf(a, b, c).any { it == null }

listOf(a, b, c).filterNotNull().any()

In context, this is how you can use it:

println(if (listOf(a, b).any { it == null })) "Something went wrong"
        else "Everything ok.")
Unriddle answered 8/10, 2018 at 8:23 Comment(1)
While this approach is the most concise solution I've seen and should be fine in most cases, the issue I'm having with it is that it doesn't smart cast to non-null when the check only allows code to execute if there are no nulls.Singleness
S
2

You can use the Elvis operator ?:, which allows to provide a default value in case a value is null (including returning from a function).

For example:

fun foo(a: Int?, b: String?, c: Boolean?) : String? {
    a ?: return null
    b ?: return null
    c ?: return null
    return "Everything ok."
}

The advantage with this approach is that you can have different error results depending on which value is null:

  • Using exceptions:

    fun foo(a: Int?, b: String?, c: Boolean?) : String {
        a ?: throw IllegalArgumentException("a is null")
        b ?: throw IllegalArgumentException("b is null")
        c ?: throw IllegalArgumentException("c is null")
        return "Everything ok."
    }
    
  • Using different return values:

    fun foo(a: Int?, b: String?, c: Boolean?) : Result {
        a ?: return Result.ErrANull
        b ?: return Result.ErrBNull
        c ?: return Result.ErrCNull
        return Result.OK("Everything ok.")
    }
    
    sealed class Result {
        class OK(val s: String) : Result()
        object ErrANull : Result()
        object ErrBNull : Result()
        object ErrCNull : Result()
    }
    
Solanum answered 5/4, 2023 at 7:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.