Kotlin Null Safety

Eliminate NullPointerException with nullable types, safe calls, Elvis operator, and smart coding habits

String? ?. ?: !!

Table of Contents

1Nullable Types

In Kotlin, types are non-null by default. A variable of type String cannot hold null. To allow null, append ? to create a nullable type such as String?. The compiler enforces null checks at compile time.

Non-null vs nullable

Nullable vs non-null typesfun main() { var name: String = "Nikhil" // name = null // Compile error: Null cannot be assigned to non-null String var nickname: String? = "Nick" nickname = null // OK — String? allows null println(name) println(nickname) // null }
TypeCan be null?Example
StringNoval title: String = "Hello"
String?Yesval middleName: String? = null
IntNoval age: Int = 25
Int?Yesval score: Int? = null

Nullable function parameters and returns

Nullable in functionsfun findUser(id: Int): String? { return if (id == 1) "Nikhil" else null } fun greet(name: String?) { if (name != null) { println("Hello, $name") } else { println("Hello, Guest") } } fun main() { greet(findUser(1)) // Hello, Nikhil greet(findUser(99)) // Hello, Guest }

Kotlin vs Java null handling

AspectJavaKotlin
DefaultAny reference can be nullNon-null by default
NPE timingRuntime crashMany cases caught at compile time
Syntax@Nullable / @NonNull annotations? in type system
Smart cast: After an explicit if (x != null) check, Kotlin automatically treats x as non-null inside that block — no manual cast needed.

2Safe Calls

The safe call operator ?. calls a method or accesses a property only if the receiver is non-null. If the receiver is null, the entire expression evaluates to null without throwing an exception.

Safe call operator ?.fun main() { val name: String? = "Nikhil" val empty: String? = null println(name?.length) // 6 println(empty?.length) // null (no crash) println(name?.uppercase()) // NIKHIL println(empty?.uppercase()) // null }

Chained safe calls

Safe call chainsdata class Address(val city: String?) data class User(val name: String, val address: Address?) fun main() { val user: User? = User("Alex", Address(null)) val city = user?.address?.city?.uppercase() println(city) // null — safe chain stops at null city val user2: User? = null println(user2?.name) // null }

Safe calls with let

Combine ?. with let to run a block only when a value is non-null:

?.let { }fun main() { val email: String? = "user@example.com" email?.let { validEmail -> println("Sending to $validEmail") } val missing: String? = null missing?.let { println("This never runs") } }

Operator reference

OperatorNameBehavior
?.Safe callCall/access only if non-null; else null
?[index]Safe indexSafe array/list access on nullable receiver
as?Safe castReturns null if cast fails (no ClassCastException)
Android example

binding?.textView?.text = userName — safely update UI when binding or view might be null during lifecycle transitions.

3Elvis Operator

The Elvis operator ?: provides a default value when the left side is null. It is one of Kotlin's most used operators for concise null handling.

Elvis operator ?:fun main() { val nickname: String? = null val displayName = nickname ?: "Guest" println(displayName) // Guest val score: Int? = 85 val finalScore = score ?: 0 println(finalScore) // 85 }

Combining safe call and Elvis

?. combined with ?:fun main() { val input: String? = null val length = input?.length ?: 0 println("Length: $length") // Length: 0 val name: String? = "Kotlin" println(name?.length ?: 0) // 6 }

Elvis with early return

Elvis for guard clausesfun processUser(name: String?) { val validName = name ?: return println("Processing $validName") } fun getLength(text: String?): Int { return text?.length ?: throw IllegalArgumentException("text cannot be null") } fun main() { processUser("Nikhil") // Processing Nikhil processUser(null) // returns silently }

Common patterns

PatternCodeResult if null
Default stringname ?: "Unknown""Unknown"
Default numbercount ?: 00
Empty collectionlist ?: emptyList()Empty list
Parse or defaultinput.toIntOrNull() ?: 00
Name origin: ?: looks like Elvis Presley's hair from the side — hence "Elvis operator."

4Non-Null Assertion

The non-null assertion operator !! converts a nullable type to a non-null type. If the value is actually null at runtime, Kotlin throws a NullPointerException.

Non-null assertion !!fun main() { val name: String? = "Nikhil" println(name!!.length) // 6 — OK val missing: String? = null // println(missing!!.length) // NPE at runtime! }

When !! might be acceptable

ScenarioReason
Immediately after null check elsewhereYou are certain value is non-null
Test code / prototypesQuick and dirty; not for production
Interop with Java APILegacy code guaranteed non-null (use sparingly)

Better alternatives to !!

Prefer safe alternativesfun main() { val value: String? = getValue() // Avoid: // val len = value!!.length // Prefer: val len = value?.length ?: 0 // Or smart cast after check: if (value != null) { println(value.length) // smart cast — no !! needed } } fun getValue(): String? = "Hello"
Warning

Treat !! as a code smell in production. It disables Kotlin's compile-time null safety and brings back Java-style NPE crashes. Prefer ?., ?:, smart casts, or explicit checks.

5Null Safety Best Practices

Follow these habits to write safer, cleaner Kotlin code in apps, libraries, and backend services.

Prefer non-null types

Default to String, Int, etc. Use ? only when null is a valid business state.

Use Elvis for defaults

value ?: default is readable and avoids nested if-null checks.

Chain safe calls

user?.profile?.avatar?.url — short-circuits safely on any null link.

Avoid !!

Replace with smart casts, requireNotNull, or early returns.

1. Use lateinit and by lazy appropriately

lateinit vs lazyclass MainActivity { // lateinit — non-null var initialized later (not for primitives) lateinit var adapter: RecyclerView.Adapter<*> // lazy — computed once on first access val config: Config by lazy { loadConfig() } }

2. Use requireNotNull and checkNotNull

Explicit null checks with messagesfun saveUser(name: String?) { val validName = requireNotNull(name) { "Name is required" } println("Saving $validName") } fun parseId(id: String?): Int { return checkNotNull(id?.toIntOrNull()) { "Invalid id: $id" } }

3. Model optional data explicitly

Nullable fields in data classesdata class User( val id: Int, val name: String, val email: String?, // optional val phone: String? = null // optional with default ) fun main() { val user = User(1, "Nikhil", null) println(user.email ?: "No email on file") }

4. Platform types from Java

When calling Java code, Kotlin sees platform types (e.g. String!) — the compiler doesn't know if they're nullable. Treat Java return values as nullable unless documented otherwise.

Java interop caution// Java method: public String getName() { return maybeNull(); } // Kotlin sees platform type String! fun handleJavaName(javaUser: JavaUser) { val name = javaUser.name ?: "Unknown" // safe default }

5. Decision guide — which operator to use?

SituationRecommended approach
Need default if nullvalue ?: default
Call method only if non-nullvalue?.method()
Run block only if non-nullvalue?.let { }
Already checked null in ifSmart cast — use value directly
Must fail if nullrequireNotNull(value)
"I know it's not null"Prove it with logic — avoid !!
Sealed classes for state: Instead of nullable UI state, use sealed classes like Loading, Success(data), Error(msg) — covered in Data, Enum & Sealed Classes.

6Summary Cheatsheet

TopicKey Takeaway
Nullable TypesString = non-null; String? = may be null
Safe Calls?. — returns null instead of NPE
Elvis Operator?: — default value when left side is null
Non-Null Assertion!! — forces non-null; throws NPE if wrong
Best PracticesPrefer non-null types, Elvis, let; avoid !!; handle Java platform types
HelpersrequireNotNull, checkNotNull, smart cast, lateinit
Next lessonOOP in Kotlin — classes, inheritance, properties

Kotlin Null Safety MCQ Practice

10 Basic MCQs 10 Advanced MCQs

10 Basic Kotlin Null Safety MCQs

1

Which suffix marks a nullable type in Kotlin?

AInt!
BString?
CString*
DString@
Explanation: See Kotlin Null Safety lesson — correct answer is B.
2

Can a variable of type String hold null?

AYes, always
BNo — String is non-null by default
COnly in Android
DOnly with lateinit
Explanation: See Kotlin Null Safety lesson — correct answer is B.
3

What is the safe call operator?

A!.
B?.
C?:
D??
Explanation: See Kotlin Null Safety lesson — correct answer is A.
4

What is the Elvis operator used for?

AForce non-null
BSafe cast
CDefault value when null
DLoop break
Explanation: See Kotlin Null Safety lesson — correct answer is A.
5

Which operator throws NPE if the value is null?

A?.
B?:
C!!
Das
Explanation: See Kotlin Null Safety lesson — correct answer is C.
6

Are Kotlin types nullable by default?

ANo — types are non-null unless marked with ?
BYes — all types allow null
COnly in Java interop
DOnly for classes
Explanation: See Kotlin Null Safety lesson — correct answer is A.
7

What does user?.name return if user is null?

AThrows NPE
Bnull
CEmpty string
DUnit
Explanation: See Kotlin Null Safety lesson — correct answer is B.
8

What does name ?: "Guest" do when name is null?

AThrows exception
BUses "Guest" as default
CSkips assignment
DConverts to empty string
Explanation: See Kotlin Null Safety lesson — correct answer is A.
9

Using !! on a null reference throws?

AIllegalArgumentException
BKotlinNullPointerException
CClassCastException
DNothing — it is safe
Explanation: See Kotlin Null Safety lesson — correct answer is B.
10

What is preferred over !! for nullable chains?

ASafe call (?.) and Elvis (?:)
BJava-style if only
CAlways lateinit
DPlatform types
Explanation: See Kotlin Null Safety lesson — correct answer is A.

10 Advanced Kotlin Null Safety MCQs

11

What does obj?.let { } do?

AAlways throws
BRuns block only if obj is non-null
CConverts to String
DCreates a copy
Explanation: See Kotlin Null Safety lesson — correct answer is A.
12

lateinit is used for?

ANullable strings
BNon-null var initialized later
CCompile-time constants
DLazy delegates only
Explanation: See Kotlin Null Safety lesson — correct answer is B.
13

How do you check if a lateinit property is initialized?

AisNull()
B::prop.isInitialized
C!! always
DcheckNotNull only
Explanation: See Kotlin Null Safety lesson — correct answer is A.
14

What does the safe cast operator as? return on failure?

AThrows ClassCastException
Bnull
CUnit
Dfalse
Explanation: See Kotlin Null Safety lesson — correct answer is B.
15

Platform types from Java (String!) should be treated as?

AAlways non-null
BPossibly nullable — handle safely
CAlways null
DIgnored by compiler
Explanation: See Kotlin Null Safety lesson — correct answer is A.
16

requireNotNull(value) when value is null?

AReturns null silently
BThrows with optional message
CConverts to empty
DUses Elvis default
Explanation: See Kotlin Null Safety lesson — correct answer is B.
17

Which scope function returns the lambda result?

Aalso
Bapply
Clet
Dwith only
Explanation: See Kotlin Null Safety lesson — correct answer is A.
18

filterNotNull() on List produces?

AList without nulls
BMutable list only
CSet
DThrows on null
Explanation: See Kotlin Null Safety lesson — correct answer is B.
19

Smart cast works after?

AAny assignment
Bis check in same branch where compiler tracks stability
COnly in Java
D!! operator only
Explanation: See Kotlin Null Safety lesson — correct answer is A.
20

Best practice for API parameters that must not be null?

AUse nullable types everywhere
BUse non-null types and validate early
CUse !! at entry
DUse Java only
Explanation: See Kotlin Null Safety lesson — correct answer is A.
Click an option to select, then check answers.

Kotlin Null Safety Interview Q&A

15 topic-focused questions for interviews and revision.

1What is Kotlin null safety?easy
Answer: Kotlin distinguishes nullable (String?) and non-null (String) types at compile time, preventing many NullPointerExceptions before runtime.
2Explain the safe call operator ?.easy
Answer: ?. accesses a member only if the receiver is non-null; if the receiver is null, the whole expression evaluates to null without throwing.
3What does the Elvis operator ?: do?easy
Answer: It returns the right-hand value when the left-hand expression is null — e.g. val n = input ?: 0.
4When should you use !!?easy
Answer: Rarely — only when you are absolutely certain a value is non-null. Prefer ?., ?:, smart casts, or requireNotNull.
5Difference between String and String?medium
Answer: String cannot hold null; String? may hold null or a string value. Assigning null to String is a compile error.
6What are platform types from Java?medium
Answer: Types like String! from Java interop where nullability is unknown. Treat them as nullable or validate before use.
7Explain lateinit vs lazy.medium
Answer: lateinit var for non-null properties initialized after construction (not for primitives). lazy delegate computes on first access for val.
8How does smart cast relate to null safety?medium
Answer: After an is check or null check in a branch, the compiler automatically casts to non-null in that scope.
9What is the difference between let and also?medium
Answer: let passes the object as it and returns the lambda result. also passes it as it but returns the original object (side effects).
10How do requireNotNull and checkNotNull differ?medium
Answer: Both throw if null. requireNotNull is for public API preconditions; checkNotNull is for internal invariants and enables smart cast.
11Why avoid !! in production Android code?hard
Answer: It throws KotlinNullPointerException at runtime if wrong — crashes the app. Safe alternatives fail gracefully or use defaults.
12How do you safely chain multiple nullable calls?hard
Answer: Use ?. for each step: user?.address?.city?.name, combined with ?: for defaults at the end.
13Explain safe cast as? vs unsafe as.hard
Answer: as? returns null on failed cast; as throws ClassCastException. Prefer as? when type is uncertain.
14How does null safety help compared to Java?hard
Answer: Most null errors are compile-time. Java allows null in any reference type unless annotated; NPE is a top Android crash cause.
15When use sealed classes instead of nullable state?hard
Answer: When state is one of fixed variants (Loading/Success/Error) rather than null — exhaustive when and no invalid null states.