Kotlin Nullable Types

In many languages, variables can accidentally hold no value (called null), causing crashes at runtime. Kotlin treats null as a first-class concern — you must explicitly declare whether a variable can be null. This eliminates an entire class of bugs at compile time.

Non-Nullable vs Nullable


Non-Nullable (default):
  val name: String = "Alice"
  name = null   ← ERROR! Cannot assign null to a non-nullable type

Nullable (add ? to the type):
  var name: String? = "Alice"
  name = null   ← ALLOWED! The ? tells Kotlin null is expected

Declaring Nullable Variables

var username: String? = "Priya"
var email: String?   = null      // valid
var age: Int?        = null      // valid
var score: Double?   = 99.5      // valid

The Null Safety Problem Diagram


Without null safety (Java/Python):
  String name = getUserName()
       │
       └── What if getUserName() returns null?
  name.length   ← NullPointerException CRASH at runtime!

With null safety (Kotlin):
  val name: String? = getUserName()
  name.length   ← ERROR at compile time! Must handle null first.
  Kotlin stops you before the crash happens.

Accessing Nullable Variables

You cannot directly call methods on a nullable type without handling the null case first:

var text: String? = "Hello"

// Direct access not allowed:
// println(text.length)   ← ERROR

// Option 1: Null check with if
if (text != null) {
    println(text.length)   // safe here: Kotlin knows text is not null
}

// Option 2: Let Kotlin infer inside if block (smart cast)
if (text != null) {
    println(text.uppercase())  // text auto-cast to String here
}

Smart Cast

After a null check, Kotlin automatically treats the variable as non-nullable inside the safe block:

fun printLength(value: String?) {
    if (value == null) {
        println("Value is null")
        return
    }
    // After the null return, value is smart-cast to String
    println("Length: ${value.length}")
}

fun main() {
    printLength("Kotlin")   // Length: 6
    printLength(null)        // Value is null
}

Nullable vs Non-Nullable: Summary


Type       │ Can hold null? │ Example
───────────┼────────────────┼──────────────────
String     │ No             │ val s: String = "hello"
String?    │ Yes            │ var s: String? = null
Int        │ No             │ val n: Int = 42
Int?       │ Yes            │ var n: Int? = null

Practical Example: User Profile

data class UserProfile(
    val name: String,
    val phone: String?,      // phone may not be provided
    val bio: String?         // bio is optional
)

fun printProfile(user: UserProfile) {
    println("Name : ${user.name}")

    if (user.phone != null) {
        println("Phone: ${user.phone}")
    } else {
        println("Phone: Not provided")
    }

    if (user.bio != null) {
        println("Bio  : ${user.bio}")
    } else {
        println("Bio  : No bio available")
    }
}

fun main() {
    val u1 = UserProfile("Alice", "+1-555-1234", "Developer and coffee lover")
    val u2 = UserProfile("Bob", null, null)

    printProfile(u1)
    println("──────────────")
    printProfile(u2)
}

Output:

Name : Alice
Phone: +1-555-1234
Bio  : Developer and coffee lover
──────────────
Name : Bob
Phone: Not provided
Bio  : No bio available

Leave a Comment

Your email address will not be published. Required fields are marked *