Kotlin's two best ideas are both moves in the type system, and both get sold as conveniences, which is why people miss them. Nullability is part of a type rather than a habit, so keeping null out of places it does not belong is the compiler's job and not your discipline. And concurrency is structured: a coroutine is a child of a scope that cannot finish while the child runs, so background work cannot leak. The rest is comfort. Read this for those two, and for where the surface looks like Java but behaves differently underneath.
Each chapter opens with the short version. Tap one to read the detail.
Almost everything produces a value
~3 min
val fixes the reference, not the object behind it, and most constructs — if, when, a function body — produce a value instead of performing an action. Two sharp edges: only the expression form of when is checked for exhaustiveness, and numbers never widen implicitly.
Nullability is a type, and the compiler follows your control flow
~2 min
String and String? are different types, so a null check is assignability rather than discipline. The same flow analysis narrows a type after an is check — and where it refuses to narrow, the reason is always that the value could change between the check and the use.
Functions, lambdas, and where return actually returns from
~2 min
Default and named arguments replace most overload sets. Inside a lambda the last expression is the value, and there is no local return — a bare return exits the enclosing function, which the compiler permits only when the lambda is being inlined.
Classes: final by default, constructed from the header
~2 min
The class header is the primary constructor, and val/var there also declares a property. Classes and members are final unless marked open, and override is mandatory. Initialization runs base-first, which is why calling an open member from a constructor sees uninitialized state.
The class flavours: data, sealed, value, object
~2 min
data generates equality, toString, copy and destructuring — but only from primary-constructor properties, and copy() is shallow. sealed hands the compiler a closed set it can check a when against. object is a lazily initialized, thread-safe singleton.
Adding behaviour without inheritance: extensions, delegates, scope functions
~2 min
An extension is a function with a receiver, resolved statically on the declared type — so it never overrides anything and never behaves polymorphically. Delegates move accessor logic into a reusable object. The five scope functions differ on exactly two axes, not five.
Generics, variance, and the types that vanish
~2 min
Type arguments are erased at runtime, so x is List<String> will not compile — only List<*> is checkable. out marks a producer and in a consumer, which is why read-only List is covariant and MutableList is not. reified in an inline function is the escape hatch.
Collections: read-only is not immutable
~2 min
List is a read-only interface, not an immutable object — the data can still change through a mutable reference to it. Chained operations build a whole intermediate list at each step, unless you switch to a sequence, which pushes one element through the entire chain at a time.
Coroutines and flows: suspension is not threading
~3 min
A suspending function pauses without holding its thread, so very many coroutines share very few. Every one is a child of a scope that cannot complete while a child runs, so work cannot leak — and cancellation travels that tree, cooperatively. A flow is the streaming form of the same rules.
Living on the Java platform: interop and exceptions
~2 min
Kotlin has no checked exceptions, and throw is an expression of type Nothing. Most interop friction is two guarantees Java does not make: an unannotated Java type carries no null check, and a read-only Kotlin List is a java.util.List that Java can mutate.
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.