Hero image

Avoid null pointer exceptions by being explicit about nullability in Kotlin

Dec 18, 2023
Kotlin

Kotlin’s type system aims to avoid null references by making it explicit when a variable can be null. In Kotlin by default variables are non-nullable i.e. setting a variable to null is an error.

val name: String = null // is an error because String is non-nullable

If you want a variable to be nullable you must add a question mark ? to the end of the type.

val name: String? = null

Now any attempt to use name that could result in a NullPointerException e.g. println(name.uppercase()) will be an error forcing you to handle the null correctly.

Default Values

Often you will want to check for a null and replace it was some default value. Kotlin provides the Elvis operator ?: to do this concisely.

val name: String = nullableName ?: "Default"

When the expression on the left side of ?: is not null that value will be used otherwise the expression on the right side will be used. This is equivalent to the following in Java.

String name = nullableName;
if (nullableName == null) {
  name = "Default";
}

Safe Call Operator and Method Chaining

Kotlin also provides the safe call operator ?. to access properties and perform operations on nullable values. The safe call will behave the same as a . when the value is non-null and “circuit break” returning null when the value is null.

val nameLength: Int? = nullableName?.length

The safe call operator can be chained e.g. order?.customer?.address?.postcode will return null if any of the values in the chain are null.

This is equivalent to the following in Java. The chained example is omitted as the Java version becomes increasingly unwieldy as the chain lengthens.

Integer nameLength = null;
if (nullableName != null) {
  nameLength = nullableName.length;
}

Forced Unwrapping on a Nullable

On some rare occasions, you know better than the compile and are certain that the value is not null in this case you can use the not-null assertion operator !!. This will convert the value to a non-nullable type if it can or throw a NullPointerException if the value is null.

val nameLength: Int = nullableName!!.length

This is essentially how Java works except Java lets you do this implicitly. You’ll quickly become slightly unnerved by the !! operator as it usually comes back to bite you.

Comparison to Optional in Java

Nullable types are similar to Optionals in Java i.e. they represent the absence of a value. The use of Optional is recommended in cases where you’d return null to represent no value returned.

The Elvis operator is similar to orElse.

optional.orElse("Default");

The safe call operator is similar to map.

optional.map(s -> s.length());

The not-null assertion operator is similar to get without checking whether a value is present.

optional.get();