Kotlin null safety explained

In my Java developer’s career, NullPointerException is the single most common runtime error I encounter. And according to this research, I’m not an exception (pun intended!). Even the inventor of null reference, computer science pioneer Tony Hoare called it The Billion Dollar Mistake.

Fortunately, Kotlin introduces the concept of null safety. If you are using pure Kotlin (without mixing it with Java code) you encounter two types of references:

  1. The Non-Null type:
var nonNullReference: String = "I can't be null!"
nonNullReference = null // Compile-time error

The non-null string’s type is written as 'String'

  1. The Nullable type:
var nullableReference: String? = "I'm a nullable string"
nullableReference = null // Compiles just fine

The nullable string’s type is written as 'String?', with question mark suffix

This way we’re sure that the non-null reference will never throw dreaded NullPointerException. But what happens if we try to call some function on the nullable reference? It won’t happen because it will not compile. The compiler doesn’t care if the reference is null or not:

println(nullableReference.length) // Compile-time error

We can’t call functions on nullable references without explicitly handling the nullability. There are 3 basic ways to do that:

  1. “Classic” null check:
if (nullableReference != null) {
println(nullableReference.length)
println(nullableReference.hashCode())
println(nullableReference.capitalize())
}

This is the exact same way as every Java coder did thousands of times. Compiler knows all the uses of our nullableReference inside the if block are safe, cause we checked it’s not null before the calls are being made.

  1. Safe call:
println(nullableReference?.length)

The Kotlin safe calls are being made using the special operator '?.' - in our case, the expression println(nullableReference?.length) will not crash at runtime but instead return null. If the nullableReference wasn’t null it would return the string’s length as 'Int?' (which itself is a nullable integer).

  1. Non-null asserted call:
println(nullableReference!!.length) // NPE thrown at runtime

While using a double exclamation mark (a.k.a “double bang”) we are stating that we’re 100% sure our nullableReference is not null. This is the same behaviour as classic Java call without doing null-check. In our case, the app will crash and the NullPointerException will be thrown! This notation was made ugly on purpose, it is basically an indicator of code smell and should be used only when you want your app crash at runtime whenever there’s null reference. In most cases you should either:

But what if we are mixing Kotlin with Java?

Fortunately, when our Java code is properly annotated it will behave exactly the same as Kotlin code. Kotlin compiler recognizes many popular annotation frameworks, including Android annotations framework. If developer properly annotates the code with '@NotNull' and '@Nullable' annotations, the compiler will see those references as if they were Kotlin types. Fortunately for us mobile developers, Android framework and many popular libraries are already annotated properly.

If for whatever reason the Java code you are using wasn’t annotated, Kotlin introduces the concept of platform types. This means that whenever you are using such code, it will be treated the same as in Java. This was done for convenience (so the code wouldn’t be filled with question marks and double-bangs). The platform type string is marked as 'String!'.