Null Safety
Kotlin's headline feature: the compiler tracks nullability in the type system, gives you operators to navigate it, narrows types automatically after checks, and marks Java values as platform types. Almost every Kotlin interview spends real time here, because it is the reason many teams adopted the language.
part ofKotlinoverview, primer and where to startread it →on this pageshowhide
explore
- How Kotlin Models Absence5 questions
- Nullable Types20 questions
- Nullable vs Non-Null Types5 questions
- Nullability in Generics5 questions
- Nullable Receivers5 questions
- Definitely Non-Null Types5 questions
- Null-Handling Operators25 questions
- Safe Call Operator ?.5 questions
- Elvis Operator ?:5 questions
- Not-Null Assertion !!5 questions
- Safe Cast as?5 questions
- ?.let Idiom and Chaining5 questions
- Smart Casts15 questions
- Smart Cast After Null/Type Check5 questions
- Contract-Driven Smart Casts5 questions
- Smart-Cast Limitations5 questions
- Platform Types13 questions
- Platform Types from Java4 questions
- Honoring @Nullable/@NotNull4 questions
- Defensive Handling at the Interop Boundary5 questions
- lateinit and isInitialized9 questions
- lateinit var5 questions
- ::property.isInitialized4 questions
questions
87 · 6 sectionsIn Kotlin, what is the difference between the types `String` and `String?`, and what does the compiler do differently for each?
basics
~10 sString can never hold null; String? can. The compiler rejects assigning null to String, and forces you to handle the null case before using a String? directly.
How does Kotlin's approach to absence differ from wrapper-based Option/Maybe types (e.g. Java `Optional`, Scala `Option`, Rust `Option`)?
basics
~10 sOption/Maybe wrap a value in an extra object you must unwrap. Kotlin instead marks the type itself as nullable, so null stays the plain value — no wrapper, no unwrapping, checked by the compiler.
How does nullability interact with generics in Kotlin? Explain what `T`, `T?`, and `T & Any` mean for a type parameter, and how to express a non-null bound.
basics
~20 sAn unbounded type parameter T can itself be a nullable type, so values of T might be null. To force non-null, bound it with T : Any. Writing T? always allows null; T & Any strips nullability from a T.
What is the type of the literal `null` in Kotlin, and how do `Nothing`, `Nothing?`, `Any`, and `Any?` fit into the type hierarchy with respect to nullability?
basics
~20 snull's type is Nothing?. Nothing is the empty type at the bottom of every type; Nothing? holds only null. Any? sits at the very top (all values including null); Any is the top of all non-null values.
What are the architectural benefits and the limitations of modeling absence in the type system (compile-time) rather than at runtime, especially regarding Java interop and reflection/generics?
basics
~20 sPutting null in the type system catches missing-value bugs at compile time and documents intent for free. The catch: it's compiler-only, so Java code, reflection, and erased generics can slip null past the guarantees at runtime.
In Kotlin, what is the default upper bound of an unbounded type parameter like <T>, and what does that imply about whether T can hold null?
basics
~10 sAn unbounded <T> defaults to the upper bound Any?, which includes null. So T can hold a null value unless you restrict it.
What is a nullable receiver in Kotlin, and how does it let String?.isNullOrEmpty() be called on a null value without a NullPointerException?
basics
~20 sIt is an extension function written on a type that may be null (like String?). Because the function is defined for the null case too, you can call it on null, and inside it checks whether this is null.
In Kotlin, what is the difference between the types String and String?, and which one can hold null?
basics
~10 sString can never be null; the compiler rejects null for it. String? can hold either a real String or null. The ? means 'this might be null'.
Show how `T & Any` is used to override a Java generic method annotated `@NotNull`. Why is it needed there?
basics
~20 sWhen a Java method returns a generic value marked @NotNull, Kotlin couldn't express that the return is non-null in an override. T & Any lets the Kotlin override say 'this return is definitely not null'.
Inside generic code, how does using T differ from using T? when the parameter is declared <T : Any>? Show how each affects what values are accepted and returned.
basics
~10 sWith <T : Any>, T is always non-null, while T? adds nullability back for that specific use. So T rejects null but T? accepts it, even when T itself cannot be null.
What does the Elvis operator ?: do in Kotlin, and what is a typical example of using it?
basics
~10 sThe Elvis operator ?: gives a fallback value when the left side is null. You write a ?: b: if a is not null you get a, otherwise you get b.
What does `value?.let { ... }` do, and what is `it` inside the block?
basics
~10 sIt runs the block only when value is not null. Inside the block, it is that same value, now guaranteed non-null, so you can use it safely without extra null checks.
What does the !! operator do in Kotlin, and what happens at runtime if the value is null?
basics
~10 s!! tells the compiler to treat a nullable value as if it is definitely not null. If the value actually is null at runtime, the program crashes with a NullPointerException.
What does the safe-call operator ?. do in Kotlin, and what is the type of a?.length when a is a String??
basics
~20 s?. only calls the method or reads the property if the value on the left is not null. If it is null, the whole expression is null instead of crashing. So a?.length gives an Int? (a number or null).
What is the difference between the `as` and `as?` operators in Kotlin, and what happens at runtime when the value is not of the target type?
basics
~10 sas forces a type conversion and crashes with an exception if the value isn't that type. as? tries the same conversion but gives back null instead of crashing when the type doesn't match.
Why can you use a variable as non-null after calling requireNotNull(x) or checkNotNull(x), even though the null check happens inside a separate function?
basics
~20 sThose standard functions tell the compiler a fact: if they return normally, the argument is not null. So after the call the compiler treats the variable as non-null and lets you use it without ?. or !!.
What is a smart cast in Kotlin, and how does it work after an `if (x != null)` or `is` check?
basics
~10 sAfter you check a variable for null or for a type, Kotlin automatically treats it as the checked type inside that block. You can use it without writing an explicit cast.
Why does Kotlin let you smart-cast a nullable `val` after a null check but refuse to do the same for a `var`?
basics
~20 sA val can never change, so after you check it is not null the compiler trusts it stays not null. A var can be reassigned, maybe to null, so the compiler cannot trust the check still holds.
How does smart casting work with early returns and negated checks (e.g. `if (x == null) return`)?
basics
~10 sIf you return early when the value is null, the compiler knows that after that point the value cannot be null, so it smart-casts it to non-null for the rest of the function.
Write a custom validation helper that smart-casts its argument to non-null after the call. Explain each part of the contract DSL you use.
basics
~20 sAdd a contract { } block as the first line of the function. Inside, write returns() implies (arg != null). That tells the compiler that whenever the function returns normally, the argument was not null, so callers can use it as non-null.
A Java method returns a value Kotlin sees as a platform type (e.g. String!). How do you safely give it a default when it is null, and what does the ?: (Elvis) operator do here?
basics
~10 sUse the Elvis operator: val name = javaCall() ?: "unknown". If the left side is null, you get the value on the right. It gives a safe default instead of risking a crash.
When you call a Java method from Kotlin, how do @Nullable and @NotNull annotations on that Java method change the type Kotlin sees?
basics
~20 sIf the Java method is marked @NotNull, Kotlin treats the result as a normal non-null type. If it is @Nullable, Kotlin treats it as nullable and makes you check for null. Without an annotation, Kotlin can't tell.
What is a Kotlin platform type, how is it written, and why does calling Java code sometimes risk a NullPointerException even in Kotlin?
basics
~20 sWhen Kotlin calls Java code that doesn't say whether a value can be null, Kotlin can't tell either. It treats the value as a 'platform type' and skips its null checks, so a null can slip through and crash at runtime.
At the Java interop boundary, when do you use requireNotNull versus checkNotNull, and how do they differ from the !! operator?
basics
~10 srequireNotNull checks arguments and throws IllegalArgumentException if null. checkNotNull validates internal state and throws IllegalStateException. Both return the non-null value. !! just throws a generic NullPointerException with no message.
Contrast how Kotlin imports a Java method that is un-annotated versus one annotated @NotNull. What changes at compile time and at runtime?
basics
~10 sUn-annotated, Kotlin uses a flexible platform type and skips null checks, so a hidden null blows up later. With @NotNull, Kotlin imports a strict non-null type and trusts it, checking nullability at compile time.
What does `this::myProp.isInitialized` do, and why would you use it on a `lateinit var`?
basics
~20 sIt checks whether a lateinit property has already been given a value. If you read a lateinit property before it is set, the app crashes; this check lets you ask 'is it set yet?' first and avoid the crash.
What is `lateinit var` in Kotlin, and what problem does it solve?
basics
~10 slateinit lets you declare a non-null property without giving it a value right away. You promise to set it later before using it, so you avoid making it nullable.
What are the restrictions on what kinds of properties can be declared `lateinit`?
basics
~10 sIt must be a var, not a val. It can't be a nullable type, can't be a primitive like Int or Boolean, and can't have a custom getter or setter.
What happens if you read a `lateinit var` before it is assigned, and what exception is thrown?
basics
~10 sReading it before you set it throws an error called UninitializedPropertyAccessException. The message tells you which property wasn't initialized.
Why can you only call `isInitialized` through `this::prop` from inside the declaring class, and not on another object's lateinit property from outside?
basics
~20 sThe check needs a direct reference to that exact property, which Kotlin only gives you where the property is visible — normally inside the class that declares it. From outside you usually can't form that reference, so you can't call the check.