/** Nullability in Kotlin */

Today, I want to talk about nullable variables. This is one of my favourite topics because nullability (aka optionality in Swift) is one of the notable common themes between both Swift and Kotlin languages. It is also one of the main things that differentiates these newer native languages from their legacy predecessors, namely, Objective-C and Java.

What is Nullability?

Let’s say you want to buy a new blazer. You know that you want to buy one, but you’re not sure which blazer to get.  You will need a clothes hanger to hang it in when you eventually buy it so you decide to set up a small hanging space in your closet for this potential new blazer. So, essentially, your new blazer does not exist in your closet yet, but you do have some space for it now. 

This is the concept of nullability. If the hanging space in your closet were a variable in your program, the value it holds can be considered null because you have yet to specify the blazer it will hold. 

In programming, null value is just a placeholder that should be used when there is no value specified. Null is a just value that indicates the lack of a value. So if you create a variable and want to say that there is no value held here but you do expect that at some point during the execution, there can be a value here, you can use null. I like to think of it as similar to the colour black, which is not just a colour, but is also the absence of colour.

Using Nullability in Kotlin

Now that we understand what null is, it is important to understand that just like Swift, in Kotlin too, you cannot just use null values anywhere you like. Whenever you want to use a null value, you have to make the variable type nullable. You can do this by adding a question mark (?) after the type name.

For example, the below line of code will not compile because it is trying to assign a null value to a regular String type, which expects an actual string value:

var myString: String = null // This will not compile

To fix this, we use String? , a special type that indicates that the value can either be null or a string. Both of these values are accepted by variables of type String?. The same concept applies to all the other such types like Int?, Double?, etc.

var myString: String? = null // This is correct

N.B.: If you’re familiar with Swift, it is interesting to note that Swift also uses the same ? symbol to denote optional variables that act in a similar manner!

Tread with Care

A Null Pointer Exception, or NPE, is an exception that most programmers are familiar with. It is thrown whenever the program tries to access a value that is not found.

One of the things to keep in mind when working with nullable vs non-nullable types is that when accessing a property/function of a non-nullable type, it is always guaranteed not to throw an NPE. But when using a nullable type, if you try to access a property/function on a variable that currently holds a null value, it will cause an NPE! Consider the two examples below:

var msg1: String = "I'm non-nullable"
var length = msg1.length // This will not throw an NPE

var msg2: String? = "I'm nullable"
length = msg2.length // This will not throw an NPE
msg2 = null
length = msg2.length // This WILL throw an NPE!

In the above code, since msg1 is a regular non-nullable type, we know for a fact that it has a value and any predefined functions on such a variable are guaranteed to never to cause an NPE. However, msg2 is nullable and since we do set it to null in the second-to-last line, the last call to length function will absolutely cause an NPE!

So, it is VERY important when it comes to nullable types that we check for a null value before accessing any property/function.

Two Paths to One Goal

Kotlin provides us with two ways make sure our nullable code is safe from NPEs.

  1. The first is a rudimentary if check to compare against null value:
var msg2: String? = "I'm nullable"
msg2 = null

if (msg2 != null) {
    var length = msg2 
    print(length)
} else {
    print(null)
}

Here, we simply use the usual if-else statements to make sure that msg2 is not null before proceeding with property access.

2. The second way to prevent an NPE is to make a safe call. A safe call refers to accessing properties with ?.  operator:

var msg2: String? = "I'm nullable"
print(msg2?.length) // Prints length
msg2 = null 
print(msg2?.length) // Prints 'null'

When you use ?. in place of the . operator, the right side will be executed only if the left side is not null. Otherwise, it will do nothing and just return null as the result. It will not throw an NPE or crash the program.

N.B.: Once again, it is interesting to note that Swift also uses the same ?. symbol to allow safe access to properties and functions of optional variables! 🙂

With Great Power Comes Great Responsibility

While introducing null values into code will always add some risk of errors, programming often presents us with scenarios where null values are required. This is why newer native languages like Kotlin and Swift provide us with multiple safe ways to access such values. Utilising checks at appropriate places can help us prevent such errors, run our apps without any issues and become better programmers. So, now that you know the what and how of nullability, make sure to utilise it responsibly! Happy coding!

Leave a comment