We have already seen how Kotlin forces you to distinguish between reference
variables that can hold a
null value and those that cannot.
But Kotlin support for avoiding the so-called "billion-dollar mistake" extends
past nullable variables.
It also provides elegant and concise ways for safely handling variables that
As a reminder, by default Kotlin variables cannot be assigned a null value:
If you need a nullable variable in Kotlin, you postfix the type name with a question mark:
Your best strategy when working in Kotlin is to avoid
Keep in mind that both
try work as expressions in Kotlin, and
both can provide nice ways of ensuring that a variable always receives a value.
So instead of something like this in Java:
You can write this in Kotlin:
Note that because
s is not nullable, Kotlin will ensure that the
expression assigning it is exhaustive.
In the case above we need to add an
else statement, which also fixes the
Java example above.
The first rule of working in Kotlin is avoiding
null whenever possible.
null is not always possible or even desirable.
There are a few reasons that
null may creep into our Kotlin programs.
First, Kotlin interoperates freely with Java, which does not have as strong
So Java libraries called by Kotlin code may return vanilla Java object
references, all of which can hold
nullto Mark Missing Data
null can also be a way to indicate that a particular data field is not set or
For example, imagine that we are working with data about people modeled by the
following data class:
Lets say that we want to extend our person class to store a middle name. But we also want to represent the fact that not every person has a middle name. (Not everyone has a first or last name either, but we’re ignoring that for the sake of this example.)
We could do this one of two ways. The first way is to let the default middle name be a blank string and use that to indicate that a person does not have a middle name:
The use of a so-called sentinel value to indicate missing data is one way of
However, this approach does not always work.
For example, lets say that some people have a valid middle name that is in fact
the blank string.
Now we need to distinguish between people that lack a middle name and those that
have a middle name that is the blank string.
In this example the problem with our sentinel value is a bit contrived.
But this problem is more common when storing numeric data.
For example, we might have weather measurements, some of which lack a
In this case we could choose a temperature value that is outside of the range
that we expect to ever record—but this starts to seem inelegant.
null to mark missing fields is not a bad strategy—particularly
when working in Kotlin which allows us to handle
null more safely.
So let’s revise our example above to use
null to indicate that a person does
not have a middle name.
We also set the default middle name to be
null, allowing us to avoid passing a
middle name when constructing person objects for people that lack one.
Even if we try to avoid
null when possible, it’s safe to assume that we will
need to work with it from time to time.
Happily, Kotlin makes this easy.
First, it knows what variables might be
null, and even when they might be
Second, it provides several nice new operators for safely accessing things that
null when they could be
To start, let’s point out where we get into trouble with
null in Java: dot
Here’s our favorite example again:
o is a reference variable but does not store a reference, trying to
access its properties or methods using dot notation causes a runtime error.
Kotlin prevents this from happening:
The code above won’t even compile.
Because the Kotlin compiler has identifier that
s could be null.
And we cannot use dot notation directly on a nullable variable when it might be
Instead, Kotlin provides us with two options.
The first and far superior choice is called the safe dot operator:
It works like this:
Whenever the safe dot operator encounters a
null reference, it stops and
evaluates the entire expression to
This ensures that
null safety propagates to other variables that might be
For example, if we wanted to save the length of a nullable string:
The code above won’t compile, because Kotlin knows that
s might be
as a result knows that
s?.length might be
null, and so can’t be saved into
the non-nullable variable
If we allow Kotlin to infer the type of
l it will set it to
But this means that we can’t do math with
l, because it might be
Note also that the safe dot operator can be chained:
And also note that Kotlin propagates
null values through the chain:
To briefly map back to Java, the safe dot operator is similar to this programming pattern:
It’s just both much more convenient and enforced by the compiler when necessary.
The safe dot operator is a convenient way of working with
But it tends to propagate
null values through our programs, as shown by the
exmaple listed above:
Here we can’t work with
l as an
Int because it might be
But in many cases we need a reasonable escape hatch when computing with
something that could be
null, such as using a default value.
In the example above we’d like to use
0 in the case where the string
Of course we could do something like this:
But this is too cumbersome for something we want to make easy. Instead, Kotlin provides something called the Elvis Operator:
?: operator returns the left side if it is not
null, and the right side
Note, however, that the right side is evaluated, so the Elvis operator can
be used to short circuit function execution if certain conditions are not met:
To repeat our map back to Java, the combination of safe dot operator and Elvis operator is similar to this programming pattern:
Our best option for working with
null is to use the safe dot operator (
and combine it with the Elvis operator (
?:) to convert nullable values to
But Kotlin also provides us with a second option: the non-null assertion
Unlike the dot operator, this operator will generate a runtime exception if
and when it encounters
Essentially the non-null assertion operator mimics Java’s default behavior,
which is to throw a runtime exception when you attempt to follow a
This is normally not what we want—otherwise, why use Kotlin in the first
As a result, the operator has the fairly inconvenient and somewhat scary form
!!., with the double-bang hopefully drawing our attention to where we are
using this unsafe operator.
When we introduced Kotlin’s tools for working with
null safely, we also
pointed out that Kotlin knows when we need to use them.
And it’s knowledge about this is more sophisticated than you might think at
Clearly we don’t need to use
null safe operators when working with values that
But what about this case—a somewhat less elegant formulation of something that we could and should handle with an Elvis operator, but won’t for the sake of this example:
So it turns out that we do not need to use the safe dot operator above:
This is because the Kotlin compiler is smart enough to know that the only way
that we can end up in the
else statement is if
s is not null.
So inside that block we can work with
s as if it was a
String instead of
The Kotlin compiler’s ability to determine when a variable can be
must be handled carefully is quite powerful and nearly always correct.
But consider this case:
Here we can’t work with
s in the
else statement as a non-nullable
varibale, since it is possible that as our code was entering the
statement someone changed the value of