The difference between double-bang and safe call operators in Kotlin and when to use each

Introduction to Null Pointer Exception Errors

Henry "Dru" Onyango
4 min readJun 21, 2019

If you have programmed any object-oriented language, you are probably familiar with the danger of null reference or better known as the billion-dollar mistake

One of the most annoying short-comings of OOP languages, especially Java, is that when one tries to access a member of a null reference, the result will be a null pointer exception error or NPE for short. NPE is one of the most common errors any Java developer faces, right up there with Memory leaks and infinite looping (I have suffered all three).

The Kotlin type system was specifically designed to eliminate NPEs from the source code. So much so that among the possible causes of the error is deliberately throwing NullPointerException() or the use of “!!” also known as the double-bang operator.

Explanation around a null value and pointers

In programming, null is considered both value and pointer.

As a value, it’s a character that has its bits set to zero. This is common when used in a programming language such as C. Used as a value, it basically means the value does not exist and thus holds no memory location.

However, in a database, zero is a value and would hold memory. Thus used a pointer, null holds memory and is commonly used for uninitialized, undefined, empty, or meaningless value.

How Kotlin solves this

Kotlin separates reference that can hold null (nullable references) and those that cannot (non-nullable references). Most primitive types cannot hold null, for example, a string or a boolean cannot hold null:

var userName: String = "Henry"userName = null // Throws an exception errorvar isTrue: Boolean = trueisTrue = null // Throws an exception error

In order to make primitive types nullable, you have to explicitly tell Kotlin the type is nullable, as below:

var userName: String? = "Henry"userName = null // allowedvar isTrue: Boolean? = trueisTrue = null // allowed

Common causes of NPE

Like it or not, you will get one of these errors in Android studio. This here will be a common sight:

11-09 15:41:09.909: E/AndroidRuntime(11975): FATAL EXCEPTION: main
11-09 15:41:09.909: E/AndroidRuntime(11975): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.testing.ringer/com.testing.ringer.RingerActivity}: java.lang.NullPointerException

Null pointers are insanely common when using fragments in Android or when working with data from a server, which at some point can be null.

Let’s take this scenario, for example, you define an ArrayList and initialize it as empty like so:

var children: ArrayList<Child> = ArrayList()

Then let’s say you are fetching records from an online server and populating that ArrayList. After then, you run a loop function on that ArrayList.

And let’s assume the array from the server is empty. Instead of sending an empty array you are sent back a null. Your application will throw an NPE because you cannot perform a for loop in a null object.

Another common reason for NPE is using the double-bang operator (!!). !! turns a nullable reference to non-nullable. And this is extremely common when using making reference to the activity class inside a fragment.

An example is when you make a network call and update the UI based on the data received. Because updating needs to happen on the main thread, perform the update, like so:

... // previous code on network call
activity!!.runOnUiThread {
// Do something here
}
...

By default, the activity class inside a fragment is nullable. This is despite the fact that a fragment requires an activity to run. Adding !! means you turn the nullable reference to non-nullable. Should anything happen and the activity is not present, the application will crash with an NPE.

So, when to use !! and ?

Double-bang operator should be used in instances where you are certain that the value can never be null at any given point. To be safe, you can use it with null checkers first to ensure that the value being referenced exists. Using the previous example, this would be:

... // previous code on network call
if(activity != null) activity!!.runOnUiThread {
// Do something here
}
...

This way, the, if statement handles checking the null and the code, would never run if activity is actually null.

Personally, I’d rather use the safe call which in essence eliminates the need for the if statement. A safe call sort of runs that if statement for you. Again, using the above example, the code would look something like this:

...
activity?.runOnUiThread {
// Do something here
}
...

Using this logic, the UI thread is only called if the activity is not null.

I hope the article above provides more understanding around null pointers, NPE, double-bang operator and safe calls.

Thinking of exploring Singletons on the next articles, but feel free to drop any suggestions below.

--

--

Henry "Dru" Onyango
Henry "Dru" Onyango

Written by Henry "Dru" Onyango

Building products somewhere in Africa. Sometimes I write.

No responses yet