Null Safety in Kotlin
Tags: kotlin, functional, softwareengineering, programming
Published: 2021-03-12 00:30:07

---
title: Null Safety in Kotlin
published: true
date: 2020-06-30 03:00:06 UTC
tags: Kotlin, FunctionalProgramming, SoftwareEngineering, Programming
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7m1j9ugb3oho9lrix9ea.jpg
canonical_url: https://theanirban.dev/null-safety-in-kotlin/
---

## 1. Overview

In this article, we’ll look into the handling of null references in Kotlin.

Any programming language which has the concept of null reference throws a **_NullPointerException_**. It has been referred to as a **_billion-dollar mistake_**. [Wiki](https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions)

## 2. Nullable and Non-Nullable Type

Kotlin aims at eliminating the risk of **_NullPointerException_**. It distinguishes between nullable and non-nullable references as a part of its type system. **In Kotlin, all variables are non-nullable by default**. So, we cannot assign a null value to a variable because it’ll throw a compilation error:

```
var country: String = "India"
country = null //compilation error

```

**To define a nullable variable, we must append a question mark(?) to the type declaration:**

```
var city: String? = "Kolkata"
city = null

```

We can call a method or access a property on a non-nullable variable. However, in the case of nullable variables, we need to handle the null case explicitly. Otherwise, it will throw a compilation error since Kotlin knows that the variable contains null references:

```
val a : String = country.length
val b : String = city.length //compilation error

```

Let’s look at the different ways how we can handle null references safely in Kotlin.

## 3. Working With Nullable Types

### 3.1. Null Check

**We can use the if-else expression to explicitly check for nullable variables**. However, this option works only where the variable is immutable. Depending on the complexity of the conditions, this can also lead to nested expressions.

Let’s look at an example:

```
val city: String? = "Kolkata"
return if (city != null) {
    city.length
} else {
    null
}

```

### 3.2. Safe Call Operator (?.)

**Kotlin has a safe call operator (?.) to handle null references**. This operator executes any action only when the reference has a non-null value. Otherwise, it returns a null value. The safe call operator combines a null check along with a method call in a single expression.

Let’s see how to use a **_safe call operator_** :

```
val country: String? = "India"
assertEquals(5, country?.length)
val city: String? = null

assertNull(city?.length)

```

**In addition, we can also use the safe call operator for multiple chain calls** :

```
val country: Country? = Country(City("Kolkata", "003"))
val code: String? = country?.city?.code
assertEquals("003", code)

```

However, the chain calls return null if any of the properties are null:

```
val country: Country? = Country(null)
val code: String? = country?.city?.code

assertNull(code)

```

### 3.3. Using let() Method

We can use the **_let()_** method along with the safe call operator to act on a non-nullable variable:

```
val cities: List<String?> = listOf("Kolkata", null, "Mumbai")
var name: List<String?> = emptyList()
for (city in cities) {
    city?.let { name = name.plus(it) }
}
return name

assertEquals(2, name.size)

```

### 3.4. Using also() Method

We can use the also() method to execute additional operations like logging and printing of the non-nullable variables. **Furthermore, this method can be used in a chain with let() or run() method**.

Here's how we can use **_also()_** method along with **_let()_** method:

```
val cities: List<String?> = listOf("Kolkata", null, "Mumbai")
var name: List<String?> = emptyList()
for (city in cities) {
    city?.let {
        name = name.plus(it)
        it
    }?.also { println("Logging the value: $it") }
}
return name

assertEquals(2, name.size)

```

### 3.5. Using run() Method

We can use the **_run()_** method to execute some operations on a non-nullable reference. **This method operates using this reference and returns the value of the lambda result** :

```
val countries: List<String?> = listOf("India", null, "Germany")
var name: List<String?> = emptyList()
for (country in countries) {
    country?.run {
        name = name.plus(this)
        this
    }?.also { println("Logging the value: $it") }
}
return name

assertEquals(2, name.size)

```

### 3.6. Elvis Operator (?:)

**We can use the Elvis operator (?:) to return a default value only if the original variable has a null value**. If the left-side expression of the Elvis operator has a non-nullable value, then it is returned. Otherwise, the right-side expression is returned.

Let’s take a look at how the **_Elvis operator_** works:

```
val country: Country? = Country(City("New Delhi", null))
val result = country?.city?.code ?: "Not available"

assertEquals("Not available", result)

```

**We can use the Elvis operator with a safe call operator to invoke a method or property of the variable** :

```
val country: Country? = Country(City("Mumbai", "002"))
val result = country?.city?.code ?: "Not available"

assertEquals("002", result)

```

**We can also use throw and return expression in the right-side expression of the Elvis operator**. So instead of default values, we can throw specific exceptions in the right-side expressions of the Elvis operator:

```
val country: Country? = Country(City("Chennai", null))
val result = country?.city?.code ?: throw IllegalArgumentException("Not a valid code")

assertThrows<IllegalArgumentException> { result }

```

### 3.7. Not Null Assertion Operator (!!)

**We can use the not-null assertion operator (!!) to explicitly throw a NullPointerException**. This operator converts any reference to its non-nullable type and throws an exception if the reference has a null value. Let’s have a look into how we can throw **_NullPointerException_** using **_not-null assertion operator(!!)_**:

```
val country: String? = null
val result : Int = country!!.length
assertThrows<NullPointerException> { result }

```

However, if the reference has a non-nullable value, then it is executed successfully:

```
val country: String? = "India"
val result : Int = country!!.length
assertEquals(5, result)

```

**The not-null assertion operator should be used carefully since it’s a potential sign of a NullPointerException**. We should avoid using **_multiple non-null assertions_** like the following since it makes it harder to debug which property is null:

```
country!!.city!!.code

```

Additionally, **We should always try to use safe call operator in such cases to ensure NullPointerException doesn’t occur** :

```
country?.city?.code

```

## 4. Nullability in Collections

**Kotlin collections are non-nullable by default**. So, in order to define a collection of nullable types in Kotlin, we have to append the question mark (?) to the type declaration:

```
val countries: List<String?> = listOf("India", null, "Germany", "Russia", null)

```

We can use the following way to define a nullable collection in Kotlin:

```
var countries: List<String>? = listOf("India", "Germany", "Russia")
countries = null

```

### 4.1. Filtering Nullable Types

We can filter a list that contains nullable values to return only the non-nullable values using the **_filterNotNull()_** method. Let’s have a look at an example:

```
val countries: List<String?> = listOf("India", null, "Germany", "Russia", null)
val result: List<String> = countries.filterNotNull()
assertEquals(3, result.size)
assertEquals("Russia", result[2])

```

## 5. Conclusion

In this article, we look into the various ways to handle nullable references in Kotlin.

The code for these examples is available on [GitHub](https://github.com/anirban99/kotlin-examples).

_Originally published on [Anirban's Tech Blog](https://theanirban.dev/)_.