CONCEPT Cited by 1 source
Kotlin platform type¶
Definition¶
A Kotlin platform type is the type that the Kotlin
compiler assigns to a value coming from Java when the Java
side has no nullability annotation (@Nullable,
@NonNull, @Nullsafe, etc.). Written as String! in
compiler messages — "String or String?, the compiler
doesn't know". Platform types are a deliberate escape
hatch in Kotlin's type system: they let Java-derived values
participate in Kotlin code without forcing every crossing
to be annotated up-front, while keeping the runtime-check
discipline at hand.
Why it matters¶
Kotlin's core safety guarantee is that a String is
never null and a String? might be. Java has no such
guarantee at the type level — every Java reference could
be null. If Kotlin imported every Java type as String?,
idiomatic Kotlin from Java-heavy codebases would become
unusable (everything nullable all the time). If Kotlin
imported every Java type as String, Kotlin code would
silently crash any time the Java side lied.
Platform types split the difference:
- Assigning a platform value
String!to a KotlinStringinserts a runtimecheckNotNullat the boundary (see concepts/interlanguage-null-safety). If the Java value is in fact null, the check fails fast at the boundary; it does not silently flow into Kotlin code. - Assigning to
String?works without a check. - Calling a method on a platform-type value is allowed but risky — if it's secretly null, you get an NPE at dereference.
The load-bearing implication for migrations¶
Once a Java method is translated to Kotlin, the
platform-type escape hatch is gone for the translated
file's callers: the translator has to commit to String or
String? as the final declared type. Meta's
Kotlinator errs toward String?
when context is ambiguous (the safer direction), but the
final decision is irreversible in the translated file's
API surface.
The Meta post makes the downstream consequence concrete: a
pre-existing Kotlin caller that was quietly relying on the
Java method being "really" non-null (platform-typed String!
flowed through unchecked) becomes an explicit !! in the
callsite once translation pins the API to String?. Meta
calls out reviewer scrutiny on new !! outside pre-
existing dereferences as one of the most important things
to review in conversion diffs, precisely because this is
where an incorrect-but-hopeful Java annotation gets
crystallised into a production NPE.
Why this concept is distinct from "nullable type"¶
Kotlin's type system has three boundary states, not two:
| State | Source | Behaviour at Kotlin boundary |
|---|---|---|
String |
non-nullable Kotlin / @NonNull Java |
compile-time enforced |
String? |
nullable Kotlin / @Nullable Java |
compile-time enforced |
String! |
unannotated Java | runtime-checked on unboxing to non-null |
Collapsing the third into either of the first two is incorrect in interop-heavy codebases. Platform types are the mechanism that keeps Java interop tractable without silently dropping the null safety Kotlin otherwise gives.
Canonical wiki reference¶
sources/2024-12-18-meta-translating-10m-lines-of-java-to-kotlin — Meta's 2024-12-18 post is the wiki's canonical backing for platform types as a load-bearing concept for large Java-to-Kotlin migrations. Official Kotlin spec reference: kotlinlang.org/docs/java-interop.html#null-safety-and- platform-types.
Related¶
- concepts/interlanguage-null-safety — the parent concept.
- concepts/runtime-nullability-telemetry — Meta's approach to closing the platform-type inference gap at scale.
- systems/kotlinator — the migration pipeline that has to commit platform types to concrete nullability.
- systems/nullsafe + systems/nullaway — the Java- side annotations whose absence creates platform types in the first place.