Chapter 3: Variables, Data Types & Null Safety (Kotlin’s Killer Feature)
Kotlin’s null safety is often called its killer feature — it practically eliminates the infamous NullPointerException (NPE) that has haunted Java developers for decades.
We’re going to go super slowly, like we’re sitting together in a Bandra café with cutting chai ☕, and I’ll explain every single concept with lots of real-life analogies, copy-paste examples, step-by-step breakdowns, tables, common mistakes, and fun facts so everything sticks perfectly.
Let’s begin!
1. val (Immutable) vs var (Mutable) – The Foundation
In Kotlin, you declare variables in two ways:
| Keyword | Meaning | Can be reassigned? | Real-life analogy |
|---|---|---|---|
| val | Value – read-only | No – once set, cannot change | Like a printed book – you can read it, but you can’t change the text |
| var | Variable – mutable | Yes – can be changed later | Like a notebook – you can erase and write new values |
Important rule: Always prefer val unless you really need to change the value later. This makes your code safer, more predictable, and easier to reason about.
Example – val vs var
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
fun main() { // Immutable – good practice val name = "Webliance" // name = "Amit" // ERROR! Cannot reassign val // Mutable – only when needed var age = 25 println("Initial age: $age") // 25 age = 26 // OK! println("Updated age: $age") // 26 // val can be assigned only once val city: String city = "Mumbai" // OK – first assignment // city = "Pune" // ERROR! } |
Fun fact: In real Kotlin code (especially Android & backend), ~80–90% of variables are val — that’s how powerful and safe it is!
2. Type Inference – Kotlin’s Smartness
Kotlin infers (guesses) the type automatically — you don’t have to write it every time.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
val name = "Priya" // Kotlin knows it's String val age = 24 // Kotlin knows it's Int val salary = 85000.50 // Kotlin knows it's Double val isStudent = true // Boolean // But you can still write type explicitly (optional) val city: String = "Pune" val marks: Double = 92.75 |
When to write type explicitly?
- When the compiler cannot infer (rare)
- When you want to make code more readable for others
- When working with ambiguous literals (e.g., 1 could be Int or Long)
|
0 1 2 3 4 5 6 7 |
val bigNumber = 1000000000000 // Int – but too big → error! val bigNumberLong: Long = 1000000000000 // OK |
3. All Basic Data Types in Kotlin
Kotlin has almost the same basic types as Java, but they are all objects under the hood (no primitives like Java’s int vs Integer).
| Type | Size / Range | Example Literal | Default Value |
|---|---|---|---|
| Int | 32-bit integer | 42, 1_000_000 (underscores OK) | 0 |
| Long | 64-bit integer | 42L, 1_000_000_000L | 0L |
| Double | 64-bit floating point | 3.14, 9.8e2 | 0.0 |
| Float | 32-bit floating point | 3.14f, 9.8e2f | 0.0f |
| Boolean | true / false | true, false | false |
| Char | Single 16-bit Unicode character | ‘A’, ‘न’, ‘\u20B9’ (₹) | — |
| String | Sequence of characters | “Hello”, “नमस्ते” | — |
Special Kotlin features for literals:
|
0 1 2 3 4 5 6 7 8 9 10 |
val million = 1_000_000 // Underscores for readability val billion = 1_000_000_000L // Long val pi = 3.14159 // Double val taxRate = 18.0f // Float val rupee = '\u20B9' // Char – ₹ symbol |
String templates (super powerful):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
val name = "Webliance" val age = 25 val greeting = "नमस्ते $name! तुम्ही $age वर्षांचे आहात!" // Easy! println(greeting) // Complex expression inside ${} val message = "Next year you will be ${age + 1} years old!" |
4. Nullable Types – Kotlin’s Killer Feature (Null Safety)
In Java → String name = null; → name.length() → NullPointerException crash!
In Kotlin:
- By default → non-nullable (cannot hold null)
- Add ? to make it nullable
|
0 1 2 3 4 5 6 7 8 9 10 |
val name: String = "Webliance" // Non-nullable – cannot be null // name = null // ERROR! val nickname: String? = null // Nullable – OK // nickname.length() // ERROR! Compiler stops you |
Safe ways to handle nullable types
| Operator / Technique | What it does | Example |
|---|---|---|
| Safe call ?. | Call only if not null, else return null | nickname?.length → null if nickname is null |
| Elvis operator ?: | Return left if not null, else right (default) | nickname ?: “Guest” |
| Not-null assertion !! | I promise it’s not null – crash if it is | nickname!!.length (dangerous!) |
| Smart cast | Compiler automatically knows after check | if (nickname != null) { nickname.length } |
| let { } | Safe scope when not null | nickname?.let { println(it.length) } |
Example – All in Action
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
fun main() { var email: String? = null // Safe call println(email?.length) // null (no crash!) // Elvis operator val displayName = email ?: "Guest" println("Welcome, $displayName") // Welcome, Guest // Safe with let email?.let { println("Email length: ${it.length}") } ?: println("No email provided") // Dangerous – only use when 100% sure! // email!!.length // Crash if null! } |
5. Platform Types & Java Interop Nullability
When calling Java code from Kotlin, Kotlin doesn’t know if a Java type is nullable or not → it becomes a platform type (marked with !).
Example:
|
0 1 2 3 4 5 6 7 |
val javaList: java.util.ArrayList<String> = java.util.ArrayList() // javaList is ArrayList<String!> – platform type |
How to handle:
|
0 1 2 3 4 5 6 7 |
val length = javaList.get(0)?.length // Safe call val safeList = javaList ?: emptyList() // Elvis |
Best practice: Use nullability annotations in Java code (@Nullable, @NotNull from JetBrains or AndroidX) → Kotlin understands them perfectly.
6. Quick Recap Table (Your Cheat Sheet)
| Concept | Kotlin Way (Best Practice) | Java Equivalent (for comparison) |
|---|---|---|
| Immutable variable | val name = “Webliance” | final String name = “Webliance” |
| Mutable variable | var age = 25 | int age = 25 |
| Type inference | val city = “Mumbai” (no type needed) | Must write String city = “Mumbai” |
| Nullable type | String? | String (can be null) |
| Safe call | name?.length | if (name != null) name.length() |
| Elvis operator | name ?: “Guest” | name != null ? name : “Guest” |
| Not-null assertion | name!! | (String) name (risky cast) |
7. Homework for You (Let’s Make It Fun!)
- Basic Declare 5 val variables: your name, age, city, salary (Double), isStudent (Boolean). Print them using string templates.
- Medium Create a nullable String? email variable. Print its length using safe call and Elvis operator.
- Advanced Write a function fun greet(name: String?) that prints “नमस्ते $name!” if name is not null, else “नमस्ते Guest!”
- Fun Create a var score = 85. Increase it by 10, then print “Your new score is $score!” using string template.
- Challenge Fix this buggy code:
Kotlin01234567val message: String? = nullprintln(message.length) // Crash!
You’ve just unlocked Kotlin’s superpower — null safety! This single feature saves millions of hours of debugging worldwide.
