Kotlin Null Safety

Kotlin’s type system is aimed to eliminate the jeopardy of null reference from the code because it is a billion dollar mistake. NullPointerExceptions are thrown by the program at runtime and sometimes cause application failure or system crashes.
If anybody has been programming in Java or other language that has concept of null reference then he must has experienced about NullPointerException in the code. Kotlin compiler also throws NullPointerException if it found any null reference without executing any other statements.

The possible causes of NullPointerException’s are following:

  • Explicit call to throw NullPointerException()
  • Use of the !! operator
  • Some data inconsistency with regard to initialization e.g. an uninitialized this is passed as an argument.
  • Java interoperations such as attempts to access a member on a null reference , generics type with incorrect nullability.

Nullable and Non-Nullable Types in Kotlin –

Kotlin type system has distinguish two types of references that can hold null (nullable references) and those that can not (non-null references).



A variable of type String can not hold null. If we try to assign null to the variable, it gives compiler error.

var s1: String = "Geeks"
s1 = null // compilation error

To allow a variable to hold null, we can declare a variable as nullable string, written String?

var s2: String? = "GeeksforGeeks"
s2 = null // ok
print(s2)

Now, if we want to access the length of the string s1, it guarantees not to throw NPE, so we can safely say:

val l = s1.length

But if we want to access the length of the string s2, that would not be safe, and the compiler reports an error:

val l = s2.length         // error: variable 's2' can be null

Kotlin program of non-nullable type –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>){
    // variable is declared as non-nullable
    var s1 : String = "Geeks"
  
    //s1 = null  // gives compiler error
      
    print("The length of string s1 is: "+s1.length)
}

chevron_right


Output:

The length of string s1 is: 5

Here, if we try to assign null to a non-nullable variable then it gives compiler time error. But, if we try to access the length of the string then it guarantees not to through NullPointerException.

Kotlin program of nullable type-

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // variable is declared as nullable
    var s2: String? = "GeeksforGeeks" 
      
    s2 = null    // no compiler error 
      
    println(s2.length)  // compiler error because string can be null
}

chevron_right


Output:

Error:(8, 15) Kotlin: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?

Here, we can easily assign null to a nullable type variable. But we should use the safe operator to get the length of the string.


Checking for null in conditions –

The most common way of checking null reference is using if-else expression. We can explicitly check if variable is null, and handle the two options separately.

Kotlin program of checking null in conditions –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // variable declared as nullable
    var s: String? = "GeeksforGeeks"
    println(s)
    if (s != null) {
        println("String of length ${s.length}")
    } else {
        println("Null string")
    }
    // assign null
    s = null
    println(s)
    if (s != null) {
        println("String of length ${s.length}")
    } else {
        println("Null String")
    }
}

chevron_right


Output:

GeeksforGeeks
String of length 13
null
Null String

Note that we have used if-else block to check the nullability. If string contains null then it executes the if block else it executes the else block.

Safe Call operator(?.) –

Null Comparisons are simple but number of nested if-else expression could be burdensome. So, Kotlin has a Safe call operator, ?. that reduces this complexity and execute an action only when the specific reference holds a non-null value.. It allows us to combine a null-check and a method call in a single expression.

The following expression:

firstName?.toUpperCase()

is equivalent to:

if(firstName != null) 
    firstName.toUpperCase()
else
    null 

Koltin program of using safe operator –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // variable declared as nullable
    var firstName: String? = "Praveen"
    var lastName: String? = null
  
    println(firstName?.toUpperCase())
    println(firstName?.length)
    println(lastName?.toUpperCase())
}

chevron_right


Output:

PRAVEEN
7
null

We can use the safe call operator with let(), also() and run() if value is not null-


let() method –
To execute an action only when a reference holds a non-nullable value, we can use a let operator. The lambda expression present inside the let is executed only if the variable firstName is not null.

val firstName: String? = null
firstName?.let { println(it.toUpperCase()) }

Here, the variable firstName is null, so the lambda expression is not executed to convert the string to Upper Case letters.

Kotlin program of using let –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // created a list contains names
    var stringlist: List<String?> = listOf("Geeks","for", null, "Geeks")
    // created new list
    var newlist = listOf<String?>()
    for (item in stringlist) {
        // executes only for non-nullable values
        item?.let { newlist = newlist.plus(it) }
    }
    // to print the elements stored in newlist
    for(items in newlist){
        println(items)
    }
}

chevron_right


Output:

Geeks
for
Geeks

also() method chain with let() –
If we want to apply some additional operation like printing the non-nullable items of the list we can use an also() method and chain it with a let() or run():

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // created a list contains names
    var stringlist: List<String?> = listOf("Geeks","for", null, "Geeks")
    // created new list
    var newlist = listOf<String?>()
    for (item in stringlist) {
        // executes only for non-nullable values
        item?.let { newlist = newlist.plus(it) }
        item?.also{it -> println(it)}
    }
}

chevron_right


Output:

Geeks
for
Geeks

run() method –
Kotlin has a run() method to execute some operation on a nullable reference. It seems to be very similar to let() but inside of a function body, the run() method operates only when we use this reference instead of a function parameter:

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    // created a list contains names
    var stringlist: List<String?> = listOf("Geeks","for", null, "Geeks")
    // created new list
    var newlist = listOf<String?>()
    for (item in stringlist) {
        // executes only for non-nullable values
        item?.run { newlist = newlist.plus(this) } // this reference
        item?.also{it -> println(it)}
    }
}

chevron_right


Output:

Geeks
for
Geeks

Elvis Operator(?:) –

The Elvis operator is used to return a non-null value or a default value when the original variable is null. In other words, if left expression is not null then elvis operator returns it, otherwise it returns the right expression. The right-hand side expression is evaluated only if the left-hand side found to be null.

The following expression:


val name = firstName ?: "Unknown"

is equivalent to:

val name = if(firstName!= null) 
         firstName
      else 
         "Unknown"

Moreover, we can also use throw and return expressions on the right side of Elvis operator and it is very useful in functions. Hence, we can throw an exception instead of returning a default value in the right side of Elvis operator.

val name = firstName ?: throw IllegalArgumentException("Enter valid name")

Kotlin program of using Elvis operator –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    var str : String?  = "GeeksforGeeks"
    println(str?.length)
    str = null
    println(str?.length ?: "-1")
      
}

chevron_right


Output:

13
-1

Not null assertion : !! Operator

The not null assertion (!!) operator converts any value to a non-null type and throws an exception if the value is null.
If anyone want NullPointerException then he can ask explicitly using this operator.

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    var str : String?  = "GeeksforGeeks"
    println(str!!.length)
    str = null
    str!!.length
}

chevron_right


Output:

13
Exception in thread "main" kotlin.KotlinNullPointerException
    at FirstappKt.main(firstapp.kt:8)


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.