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?
answer
- Java return = platform type T!, no compiler null check
- ?: returns left if non-null, else right
- Assign to explicit Kotlin type at the boundary
- RHS can be throw/return, not just a value
- Result type is non-null when fallback guarantees a value
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.
solid answer
~40 sJava has no null-tracking, so Kotlin treats Java return values as platform types (written T! in errors). The compiler trusts you and inserts no null check, so a null can slip in and later blow up. The defensive move is to assign it to a Kotlin type immediately and supply a fallback with the Elvis operator ?:. `val name: String = javaCall() ?: "unknown"` evaluates the left expression once; if it is non-null that value is used, otherwise the right side is. The right side can be any expression of a compatible type, including `throw`, `return`, or a computed default. This pulls the unknown nullability into an explicit, non-null Kotlin type at the boundary, so the rest of your code never has to think about it.
code
kotlin · 5 lines// Java boundary: getCity() returns String! (platform type)
val city: String = address.city ?: "N/A"
// Fallback that fails fast instead of defaulting:
val port: Int = config.port ?: throw IllegalStateException("port missing")go deeper
Knows Elvis gives a default and prevents a crash on null.
Explains platform types, why the boundary needs conversion, and the resulting non-null type.
Uses ?: with throw/return to fail fast and standardizes converting platform types at the entry point.
Establishes team-wide boundary-hardening conventions and wraps untrusted Java libraries behind Kotlin-typed adapters.
## The problem: platform types When Kotlin calls Java, the Java type system carries no nullability information (ignoring annotations). Kotlin therefore assigns a **platform type**, shown in diagnostics as `String!` (the `!` means "nullable or not — compiler won't check"). The compiler does **not** force you to null-check it, which is convenient but dangerous: a `null` can flow into a non-null Kotlin variable and throw a `NullPointerException` later, far from the source. ## The Elvis operator `?:` The Elvis operator takes the form `a ?: b`. It evaluates `a`; if `a` is non-null it returns `a`, otherwise it returns `b`. The right-hand side is only evaluated when needed (short-circuit). ```kotlin // Java: String User.getNickname() -> Kotlin sees String! val nickname: String = user.nickname ?: "anonymous" ``` Here the result type is the **non-null** `String`, because the fallback guarantees a value. ## Why do it at the boundary The rule of thumb: **convert platform types to explicit Kotlin types the moment they enter your code**. Declaring `val nickname: String = ...` forces the compiler to insert an `Intrinsics.checkNotNullExpressionValue` style check, so if `null` does arrive you fail right there, not three layers deep. ## Right-hand side can short-circuit control flow The fallback can throw or return: ```kotlin val id: Long = record.id ?: throw IllegalStateException("record has no id") val token = header() ?: return null ``` ## Related operators - `?.` (safe call) — call a member only if the receiver is non-null, else the whole expression is null. - `?.let { }` — run a block only when non-null. - `!!` — assert non-null, throwing `NullPointerException` if wrong (avoid; it discards information about *why*). Elvis is the workhorse for supplying defaults; `!!` is the lazy, blunt alternative.
- What is the type of `user.nickname ?: "anonymous"` when nickname is String!?String (non-null) — the Elvis fallback supplies a guaranteed value, so the expression cannot be null.
- Is the right-hand side of ?: always evaluated?No. It is evaluated lazily, only when the left side is null (short-circuit).
Elvis is a safety net under a tightrope: if the value falls (is null), the net (default) catches it instead of letting it hit the ground.
saying these in an interview costs you the question
- Claiming the compiler forces a null check on Java return values
- Using !! everywhere instead of a meaningful fallback
- Thinking ?: returns the right side when left is non-null
- Believing the RHS is always evaluated
- Saying platform types are the same as nullable types