Android Then and Now: NullPointerException

Jamie Sanson
Trade Me Blog
Published in
4 min readMay 14, 2021
Image by Arek Socha from Pixabay

Welcome to the fourth instalment in this series of byte-sized blog posts, where we look at Android Then and Now. We’ll go through bits and pieces of Android development that have changed, and look at why and how they are what they are today in less than five minutes of reading. We’ll cover things like layouts, dependency management, background work, camera usage, navigation and much more!

This time, let’s talk null.

Plain old Java

In the beginning, there was Java.

There are a bunch of reasons why Java was chosen as the programming language of choice for Android development, most of which stem from key benefits of virtual machines: isolation, and portability. The decision to go with Java was probably made early on in Android’s history, and the ramifications of that decision are still showing up to this day, with later additions causing a case to escalate to the Supreme Court.

One of the ramifications we’ve had to manage as developers is the fact that in Java, fields, variables and parameters can be null. Null represents an absent value, and trying to operate on a value which isn’t there throws an exception. Doing the following is a bad idea, and will cause your app to crash:

Instead, good programming practice was (and still is) to program defensively. This means null checks:

In some cases, you could expect things to never be null. You might null check parameters before passing them into a method. If you have that at all the callsites of the method, you’re safe!

However, someone might come along and write new code which passes null in to your method anyway, so you might consider writing a null check within the method anyway to be defensive. This leads to duplication.

Java + Nullness Annotations

NullPointerExceptions were so rampant and devastating in Java-based applications that annotations were introduced to warn the developer about potential issues while writing the code. This means more certainty around when you need to defensively null check.

Lint can then infer nullness issues in and around this annotated code, and can generate warnings to hint at where unsafe code might exist. As time went on nullness annotations appeared in a lot of important SDKs, with the Android SDK itself gradually annotating its entire public API surface. Given the incremental approach, NullPointerExceptions slowly declined in prevalence in well annotated code. Until, that is, new contenders entered the ring.

Other Languages

Instead of trying to duck tape a null-safety system together with lint, why not fix it in the type system? This is a common selling point of alternative JVM languages, including Kotlin.

Java is implicit with its nullness. Things are null if you don’t do anything with them (besides primitives). Kotlin, and other JVM languages like Scala, approach nullness by being explicit. Instead, types are implicitly not-null unless otherwise specified. Null still exists, but it’s usage is modelled and enforced by the compiler, meaning almost no NullPointerExceptions.

And thus, as Kotlin became more widely adopted in Android development, NullPointerExceptions became a thing of the past. Instead of crashing for consumers of our apps, our apps don’t compile — shifting errors left, and causing us to think more about how we model optionality.

I hope you enjoyed the fourth instalment of Android Then and Now! Next week: Finding Views. If you want to see more, follow me on Medium. Alternatively, I’ll be cross posting to my own personal blog and announcing each instalment on Twitter

--

--