0

Essentially this is in the title. I have a value that could be null. If it is, I just want to exit with a message. If it's not null, then there's a whole slew of work I need to do with this value.

I've found similar, but not quite this exact situation. And it's the subtle difference that's driving me nuts. Here is my code in java:

    if (value == null) {
        print("error!");
        return;
    }

    print(value);
    doFunStuff(value);
    etc(value);

All those methods using value require it to be non-null.

But I'm having a difficult time figuring this out in kotlin. With everything I try, the compiler still insists that value is still nullable and refuses to use it in the functions.

What is the kotlin way of doing this very common code flow?

3
  • Where did you declare value? Is it a class member? Commented Jul 19, 2021 at 14:43
  • @AdrianK value could be any variable--it could be a class member, a parameter, or even a declared var within the scope. I just used it as an abstraction to represent a variable that could be null. Perhaps I should have named it nullableVariable. Commented Aug 12, 2021 at 15:04
  • My point was, your example would be valid kotlin code, as long as value is function-local, so a parameter or local variable. But if it is not, the Kotlin compiler will always assume it might become null at any time. Commented Aug 12, 2021 at 15:36

4 Answers 4

3

Expanding on @Mehul's answer, this would only run the code in the let if the value was not null. If null, you could run the outside process and return from it.

value?.let { nonNullValue ->    
   print(nonNullValue);
   doFunStuff(nonNullValue);
   etc(nonNullValue);    
}?: run { print("error!") ; return }

That said, since you are no longer needing the return to abort the function if null, you could simply do this and further clean it up replacing the lambda.

value?.let {    
   print(it);
   doFunStuff(it);
   etc(it);    
}?: print("error!")
Sign up to request clarification or add additional context in comments.

Comments

2

If your methods truly have non-null parameters, the Kotlin compiler should be smart enough to do a smart cast to Object from Object?.

fun yourMethod(value: Object?) {
    if (value == null) {
        print("error!")
        return
    }

    print(value) // Smart cast happens here
    doFunStuff(value)
    etc(value)
}

fun print(value: Object) {
    // Implementation
}

fun doFunStuff(value: Object) {
    // Implementation
}

fun etc(value: Object) {
    // Implementation
}

But you can also force the conversion by using the !! operator (though in this case the compiler will tell you it's not necessary):

fun yourMethod(value: Object?) {
    if (value == null) {
        print("error!")
        return
    }

    val nonNullValue = value!!

    print(nonNullValue)
    doFunStuff(nonNullValue)
    etc(nonNullValue)
}

fun print(value: Object) {
    // Implementation
}

fun doFunStuff(value: Object) {
    // Implementation
}

fun etc(value: Object) {
    // Implementation
}

1 Comment

The first suggestion works sometimes, but not always. I don't know the precise conditions where the compiler complains and where it accepts the code. In the 2nd example my company has a no !! policy, even though it's integral to kotlin. Thanks for the answers!
1

If your value is a local variable or a function parameter, you won't have this problem, because the compiler will smart-cast it to not-null.

So, I'm assuming value in this case is a member property.

Option 1 is to copy it to a local variable to use in the function:

val value = value
if (value == null) {
    print("error!")
    return
}

print(value)
doFunStuff(value)
etc(value)

Option 2 is to use the let or also scope functions to do the same thing, but this might not be a good option here because so much code would become nested. This is more useful when you're only calling one or two functions with the object, in which case, you wouldn't even have to name it (just call it it).

value.let { value ->
    if (value == null) {
        print("error!")
        return
    }

    print(value)
    doFunStuff(value)
    etc(value)
}

If your entire function works with this one property, you can avoid the nesting problem like this, if you don't mind it returning something besides Unit:

fun foo() = value.also { value ->
    if (value == null) {
        print("error!")
        return
    }

    print(value)
    doFunStuff(value)
    etc(value)
}

Option 3 is to assert non-null every time you use it, but this is very ugly. This is only safe if you know the property is only ever accessed from the same thread this function is ever called on.

if (value == null) {
    print("error!")
    return
}

print(value!!)
doFunStuff(value!!)
etc(value!!)

3 Comments

Thank you for the suggestions. They do the trick, but all three are far from elegant (as you noted). Perhaps testing for null is something one should not do in kotlin.
Option 3 is the typical Java way, but the !! is there to remind you to make sure you know what you're doing. You otherwise have to test for null, unless the property is non-nullable. Generally, Kotlin encourages you to think twice before making a property nullable, because often you don't need to, and then it's easier and safer to work with that property.
I found myself using option 2 (both the let and the also variants). Still not optimal, but I don't think there's anything better in this language. Good enough for a check.
0

Well, have you already tried something like this and this is not what you expect?

value?.let { nonNullValue ->

   print(nonNullValue);
   doFunStuff(nonNullValue);
   etc(nonNullValue);

}

basically the code inside let block will run only if the value isn't null.

1 Comment

I also want to do something if the value IS null before returning (like display an error message or handle the condition directly before continuing).

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.