Kotlin Starter Pack

romainbsl
2,767 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Nullability

A feature that makes Kotlin more valuable is its type system, and the management of nullability.

Kotlin help you to avoid the in-famous NPE (NullPointerException). You have to understand that you may have NPE, even with Kotlin, but this will happen if you don't make enough effort. Kotlin will help you think about how you code in a good way.

In Kotlin, each type is consider non-null, but each of those types have a derived type nullable. Nullable types are followed by the ? character. For example, a non-null string will be written String and a nullable one will be String?.

// Variable that cannot be `null` 
var str: String = "K." 
// Variable that can be null
var str2: String?

Dealing with nullable types

Also, Kotlin provides a way to avoid NPE, when calling multiple level of nullable values. In fact, it's not an helper but some compile checks that forbid you to write unsafe code.

As you can have non-null types, you cannot assign non-null variables / parameters with null value.

var str: String = null
// Compilation error
fun strLength(s: String) = s.length
strLength(null)
// Compilation error
Accessing nullable values

For the following sections, let's assume the snippet:

data class Address(val city: String)
data class Person(val firstname: String, val lastname: String?, val address: Address?)
Safe call operator ?.

Safe-calls allow you to call properties or functions from a nullable value. It combines a null check and an invocation in a single expression. For example, s?.length is equivalent to if(s != null) s.length else null. So if you are trying to invoke a property or a function upon a null value, it will use null as the value, instead of throwing a NPE.

1
2
3
4
10
// { autofold
data class Address(val city: String)
data class Person(val firstname: String, val lastname: String?, val address: Address?)
fun main(args: Array<String>) {...}
//}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Elvis operator ?:

When dealing with nulls you may have to define default values instead of getting a null. So could write the following code:

1
2
3
4
11
// { autofold
data class Address(val city: String)
data class Person(val firstname: String, val lastname: String?, val address: Address?)
fun main(args: Array<String>) {...}
//}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Elvis operator also accept throwing exception in the right side of it.

person.address?.street ?: throw IllegalStateException("For shipping purpose, the street is mandatory")
The let function

The let function help you deals with not null values. Precede by the safe-call (?.), it can help you manipulate values inside a lambda like:

// If person.address isn't null the let function returns the address.city with uppercase
person.address?.let { it.city.toUpperCase() }

So we could write the following extension function to get the shipping address for a Person:

1
16
17
18
19
20
// {...}
val me = Person(firstname = "Romain", address = Address(city = "Nivelles", street = "1 rue de Nivelles"))
println(me.getShippingAddress())
val me2 = Person(firstname = "Romain", address = Address(city = "Nivelles"))
println(me2.getShippingAddress())
// {...}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content