Null-safe calls

With a non-null type, you may safely call methods or access properties on a variable without worrying about NullPointerException. In this snippet, languages is inferred to be List<String>. Because languages is of a non-null type, the isNotEmpty() method may be called without worrying about NullPointerException, as follows:

fun main(args: Array<String>) {
var languages = listOf("Kotlin", "Java", "c++")
languages.isNotEmpty() // okay
}

If the list were defined as List<String>?, this would not be the case. In this case, calling companies.isNotEmpty() would result in a compiler error. Because the compiler knows the value might be null, it will require you to handle that possibility in some way:

fun main(args: Array<String>) {
var languages = listOf("Kotlin", "Java", "c++")
languages.isNotEmpty() // okay

var companies: List<String>? = null
companies.isNotEmpty() // Error: Only safe (?.)
// or non-null asserted (!!.) calls are allowed
}

Perhaps the simplest way to handle the possible null value is to use a safe call. Safe calls are written using ?. and allow you to access properties or call methods without fear of NullPointerException. In this snippet, companies?.isNotEmpty() is a safe call and would return null if companies were null:

fun main(args: Array<String>) {
...

var companies: List<String>? = null
companies?.isNotEmpty() // okay
}

Safe calls can be chained together as well, making them extremely useful when accessing or assigning nested properties in a nullable type. In the following example, companies?.get(0)?.toLowerCase() will safely return null if any part of the expression evaluates to null:

fun main(args: Array<String>) {
...

var companies: List<String>? = null
companies?.get(0)?.toLowerCase() // okay
}

In this example, if student?.favoriteSubject evaluates to null, subject[0] will never be evaluated:

fun main(args: Array<String>) {
val subject = listOf("CS", "Math", "Physics")
val student: Student? = null
student?.favoriteSubject = subject[0]
}