Interview prep · Stage 1: Kotlin and DSA basics
Kotlin null safety interview questions: ?. vs !!, platform types and follow-ups
This is almost always the first Kotlin question, and the follow-ups are where interviews are won. The opener checks that you know the operators. The follow-ups check whether you understand where null safety stops: at the boundary with Java.
Try each question out loud before you open the answer.
Opening question
What is the difference between ?. and !! in Kotlin?
Show answer
val name: String? = user?.name // null if user is null
val length = name?.length ?: 0 // Elvis gives a default
val forced = name!!.length // NullPointerException if name is nullJunior answer
?. calls the member only if the value is not null, otherwise it gives null. !! throws if the value is null.
Senior answer
?. turns a nullable chain into a nullable result, so the null case stays visible in the type. !! says "I know better than the compiler" and moves the failure to runtime as a NullPointerException.
What they're really checking: They want to hear that !! moves the failure from compile time to runtime, and that you reach for ?: when there's a sensible default.
Follow-up 1
When is !! acceptable?
Show answer
// Crashes with no context
val id = intent.getStringExtra("id")!!
// Crashes with a message you can act on
val checkedId = requireNotNull(intent.getStringExtra("id")) {
"DetailActivity needs an id extra"
}Junior answer
When you are sure the value is not null.
Senior answer
Almost never in app code. If I'm sure, I'd rather make the type non-null or use requireNotNull with a message, so the crash explains itself. Tests are the one place I use it freely.
What they're really checking: "When I'm sure" is the answer that gets a follow-up. They're checking whether you know requireNotNull, checkNotNull and error(), and whether you'd rather fix the type than force it.
Follow-up 2
A Kotlin app crashes with a NullPointerException, but the code has no !!. How?
Show answer
// Java, no annotations:
// public String getNickname() { return null; }
val nick = javaUser.nickname // type is String! (platform type)
println(nick.length) // compiles, crashes at runtime
val safe: String? = javaUser.nickname // declare it nullable yourselfJunior answer
Maybe a Java library returned null.
Senior answer
Platform types. A value from Java without nullability annotations has type String!, so Kotlin lets you treat it as non-null. If Java returns null, it fails where you use it, or at the assignment if you declared the variable as non-null.
What they're really checking: This separates people who memorised the operators from people who've debugged a real crash. Bonus points for knowing Kotlin adds a null check where a platform value is assigned to a non-null type.
Follow-up 3
How would you make a Java API safe for Kotlin callers?
Show answer
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class UserRepository {
@Nullable
public String findNickname(@NonNull String id) { /* ... */ }
}
// Kotlin now sees: fun findNickname(id: String): String?Junior answer
Check for null everywhere in Kotlin.
Senior answer
Add nullability annotations such as @Nullable and @NonNull to the Java side. Kotlin reads them and gives proper nullable or non-null types, so the compiler checks every caller.
What they're really checking: They want a fix at the source, not null checks scattered through Kotlin. It's a senior signal: you fix the boundary once and every caller benefits.
Say it in 30 seconds
Show the answer
Kotlin puts null into the type system: String can't be null, String? can. With a nullable value I use ?. to keep the null visible, ?: to give a default, and a null check so the compiler smart-casts. !! forces the value and crashes if I'm wrong, so I avoid it; when a null really is a bug I use requireNotNull with a message. The gap is Java: unannotated Java values are platform types, so I treat them as nullable at the boundary, or add @Nullable and @NonNull on the Java side so the compiler checks them.