Double bang vs checkNotNull?


#1

Are there any guidelines on when one might choose !! over checkNotNull?

When using checkNotNull you’re effectively saying that you know that it should be impossible for the given value to be null, e.g. you know that a given key is present in a map so you use:

val x = checkNotNull(myMap[myKey])

However am I not saying the same thing if I use val x = myMap[myKey]!!, i.e. that I’m completely sure myMap contains myKey?

In both cases, I’m insisting that if what I assert (that the values aren’t null) is incorrect then my assumptions about the state of the world are wrong, so I prefer the IllegalStateException of checkNotNull over the NPE of !!.

So at the moment, I tend to use always checkNotNull but I’m wondering if people think there are specific situations where they feel it would be more appropriate to use !!?


#2

I personally use check/checkNotNull when I check the state of the program at the start of functions.
It’s documentation states:

Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.

As an alternative Kotlin has require/requireNotNull which throws an IllegalArgumentException. And you can use assert or !! inside of a function to check the function is working correctly. I would personally prefer assertNotNull but it does not exist.


#3

I think that !! is used not when you want to check something, but when you want to ensure compiler that the value will never be null. Check assumes that it could be null in some cases.


#4

Neither, if you see a !! something has gone really wrong.


#5

Not always. There are a few situations where the compilers reasoning about nullability is not exhaustive. One example is the compiler does not allow this due to possible multithreading

class A{
  var someVar: Foo? = something()

  fun test() {
    if(someVar != null) {
      someVar.doSomething() // error here
    }
  }
}

If you however know that this is only ever running in a single thread, you can deduce that someVar can never be null at that point. In more complex scenarios you therefor have to sometimes access variables which seem to be nullable even though they can not be null at that point.
Also I sometimes like to use !! when calling Java code to ensure it does not return null, in order to catch a NPE early.


#6

That easily fixed so it can’t call a npe.

class A{
  var someVar: Foo? = something()

  fun test() {
   someVar?.let{
     it.doSomething()
   }
    //or
    someVar?.doSomething()
  }
}

Neither of which would call a NPE because kotlin makes an immutable copy of someVar to avoid that issue.


#7

I know that this is an oversimplified version. The truth however is that there are some situations where you can not avoid it as easily.
I agree, that in general !! is a signal for badly designed code, but that does not mean that there are no legit reasons of using it sometimes.


#8

One case where it is needed (often with unsafe casts mixed in) is when writing generic containers of non-null elements (backed by a nullable array)