You are currently viewing Kotlin Null Safety

Kotlin Null Safety

Null safety is a programming concept that aims to prevent unexpected NullPointerExceptions in your code. In Kotlin, null safety is enforced by the type system, which means you must explicitly specify whether a variable or property can hold a null value (nullable) or cannot hold a null value (non-nullable).

Null Safety Prevents Runtime Crashes: Null safety helps catch potential NullPointerExceptions at compile time rather than runtime, reducing the risk of unexpected crashes in your application.

    Nullable Type(?)

    In Kotlin, every type is non-nullable by default. This means that a variable of type cannot hold a null value unless you explicitly declare it as nullable by appending ? to the type (String?). This distinction helps catch potential null pointer exceptions at compile time.

    var regularString: String = "Hello" // Non-nullable String

    If you try to assign value to the non-nullable variable, it gives compile time errors. Null can not be a value of a non-null type String

    regularString = null // compilation error

    To create nullable type you must specify whether a variable can hold null by appending a ? after the type declaration. For example:

    var name: String? = "John"
    name = null // This is valid because name is nullable

    Here, name is declared as a nullable String (String?). This means name can hold either a valid String value or a null value.

    Non-nullable Type

    A non-nullable type is a type that cannot hold a null value. When you declare a variable with a non-nullable type, Kotlin ensures that the variable always holds a non-null value throughout its lifecycle, thereby preventing NullPointerExceptions at runtime. To declare a variable with a non-nullable type, you simply specify the type without the nullable (?) modifier.

    val nonNullableString: String = "Hello"
    val nonNullableInt: Int = 42

    Kotlin’s non-nullable types provide compile-time safety against NullPointerExceptions. If you attempt to assign null to a variable with a non-nullable type, the compiler will raise an error.

    By using non-nullable types, you can catch nullability issues early in the development process, reducing the likelihood of encountering unexpected runtime errors related to null values.

    Safe Calls (?.) operator

    Kotlin provides the safe call operator (?.), which allows you to safely access properties or call methods on nullable objects. If the object is null, the call will return null instead of throwing a null pointer exception.

    It prevents a NullPointerException from occurring if the object reference is null by simply returning null instead of trying to access the property or method.

    val name: String? = null
    val length: Int? = name?.length
    print(length) // null

    Here in this example, name is declared as a nullable String initialized to null. Here name?.length Uses the safe call operator (?.) to access the length property of name.

    • If name is null, length will be null (since the safe call returns null for null receivers).
    • If name is not null, length will be the length of the String.

    Safe calls simplify code by eliminating the need for explicit null checks before accessing properties or invoking methods. This leads to cleaner and more concise code, focusing on the logic rather than handling nullability at every step.

    val name:String? = null
    var length = if (name != null) name.length else null
    println(length)//null
    
    // With safe call
    length = name?.length
    println(length)//null

    Safe calls can be chained (?.) to perform a sequence of operations on a chain of nullable properties or methods. If any part of the chain is null, the entire expression will evaluate to null without throwing an exception.

    val result = user?.address?.city?.toUpperCase()
    // 'result' will be null if any intermediate property or method call returns null

    Elvis Operator (?:)

    The Elvis operator (?:) in Kotlin is used to assign a default value when dealing with nullable references. It helps handle situations where you have a nullable variable or property, allowing you to provide a fallback value if the expression on the left side is null. This makes managing nullability more concise and straightforward.

    It’s commonly used to avoid explicit null checks and provide fallback values when dealing with nullable variables.

    The Elvis operator ?: is a concise way to handle nullable expressions and provide default values.

    The Elvis operator has the following syntax:

    expression1 ?: expression2
    • If expression1 is not null, then expression1 is returned.
    • If expression1 is null, then expression2 is returned.

    Example1 of Elvis Operator:

    val nullableName: String? = null
    val nonNullName: String = nullableName ?: "Unknown"
    println(nonNullName) // Prints "Unknown"

    In this example:

    • nullableName is null.
    • nonNullName is assigned the result of nullableName ?: "Unknown".
    • Since nullableName is null, "Unknown" is assigned to nonNullName.

    Example2 : Using with Method Call:

    fun getUserName(): String? {
        // Simulate getting username from a remote source
        return null
    }
    
    val userName: String = getUserName() ?: "Guest"
    println("Welcome, ${userName.capitalize()}") // Prints "Welcome, Guest"

    Here:

    • getUserName() returns null (simulating failure to retrieve a username).
    • userName is assigned the result of getUserName() ?: "Guest".
    • Since getUserName() is null, "Guest" is assigned to userName.

    Example3: Accessing Property of Nullable Object:

    data class Person(val name: String?)
    
    val person: Person? = Person(null)
    val personName: String = person?.name ?: "Anonymous"
    println("Person's name: $personName") // Prints "Anonymous"

      Explanation:

      • person?.name accesses the name property of person, which is null in this case.
      • personName is assigned "Anonymous" because person?.name evaluates to null.

      Not null assertion (!!) Operator :

      The not-null assertion operator (!!) in Kotlin is used to convert any value to a non-null type and throw a NullPointerException if the value is actually null. When you use !! on a nullable reference, you’re telling the compiler that you are sure the value is not null, and if it is, a NullPointerException will be thrown at runtime.

      Here’s an example to illustrate how the !! operator works:

      fun main() {
          val nullableString: String? = "Hello"
          val length = nullableString!!.length
          println("Length of the string: $length") // Output: Length of the string: 5
          
          val anotherNullableString: String? = null
          // Uncomment the line below to see the NullPointerException
          // val length2 = anotherNullableString!!.length // This will throw NullPointerException
      }

      In the example above:

      • nullableString is a nullable String? initialized with a non-null value “Hello”.
      • We use !! to assert that nullableString is not null, so nullableString!!.length retrieves the length of the string “Hello” (which is 5).
      • If nullableString were null (like anotherNullableString), using !! on it (anotherNullableString!!) would throw a NullPointerException because we are asserting that it’s not null when it actually is.

      It’s important to be cautious when using the !! operator because if used incorrectly (i.e., on a null value), it will lead to runtime exceptions. It’s generally safer and recommended to use safer alternatives like safe calls (?.) or the Elvis operator (?:) to handle nullable values and avoid potential null pointer exceptions.

      Leave a Reply