Nullability in Kotlin

Kotlins approach is to convert the well known Javas NullPointerException from runtime to compile-time error. By supporting nullability, the compiler can detect possible errors during the compilation, reducing runtime errors.

Kotlins support of nullable types
Marking a variable or property as nullable type, is a way of indicating that they are allowed to be null. In other words, if a variable can be null, calling a method on it isn’t safe. Kotlin disallows such calls.

If you don’t expect String s to be null, define the following;
fun strLen(s: String) = s.length
Calling strLen on null will be flagged as a compile error.

If you want to allow the use of this method on null values as well, you need to mark it by adding a question mark after the type name (marking it nullable):
fun strLenSafe(s: String?)

To sum up, if you don’t mark the variable as nullable, compiler understands that you don’t expect the value to be null. Compiler will complain if you’re trying to pass a nullable type to a function expecting a non null parameter. It enforces you to compare the variable with null value (deal with it in case null), once you do that, compiler remembers that and treats the value as being non-null in the scope where the check has been preformed.

Java has some tools to help solve the problem of NPE. For example annotations @Nullable an @NotNull combined with tools that can use these annotations to detect places where a NPE can be thrown. But such tools aren’t part of the standard Java compilation process, so it’s hard to ensure that they are applied consistently. Another way to solve NPE problem in Java is to avoid null values all together. Use Optionals introduced in Java 8 or Null Object Design Pattern.

Safe call operator – ?.
foo?:
-> if foo != null -> foo
-> if foo == null -> null

Safe call operator allows us to combine null check and a method call into a single operation.
Example:
s?.toUpperCase()
which translates to
if (s != null) s.toUpperCase() else null
What happens here is, if s is not null the method call is executed, if s is null, method call is skupped and null is returned.
Note taht the return type of ?.toUpperCase() isn’t String but ?String.
Safe calls can be used to access properties as well.

Elvis operator (also Null-coalescing operator) – ?:
foo?:
-> if foo != null -> foo
-> if foo == null -> arbitrary object/value
This operator works in a similar matter as Safe Call operator, with the exception that we can decide to return an arbitrary object rather than null.
Example:
s?.length ?: 0 // if s is null, the result is 0
val t: String = s ?: “” // if s is null, the result is an empty string

Not-null assertions – !!
foo!!
-> if foo != null -> foo
-> if foo == null -> NPE
This operator works in a similar matter as Safe Call operator, but in case of null value, we return a NPA instead of null. Essentially, we are telling the compiler we know the value is not null, but in case we are wrong, we are ready to deal with an exception.

The “let” function
Together with a safe-call operator, it allows us to evaluate an expression, check the result for null and store the result in a variable, all in a single expression.

Safe Cast Operator – as?

NPE = NullPointerException