Open In App

Kotlin Null Safety

Last Updated : 05 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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 – 
 

Kotlin




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)
}


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 throw NullPointerException.
Kotlin program of nullable type- 
 

Kotlin




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
}


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 – 
 

Kotlin




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")
    }
}


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 

Kotlin program of using safe operator – 
 

Kotlin




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())
}


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 – 
 

Kotlin




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)
    }
}


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()
 

Kotlin




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)}
    }
}


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: 
 

Kotlin




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)}
    }
}


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 – 
 

Kotlin




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


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.
 

Kotlin




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


Output: 
 

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

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads