Skip to content

Chapter 1 of 7

Foundations — Types, Variables, and Expressions

Kotlin's type system starts with two declarations that differ only in mutability: val creates a read-only reference that cannot be reassigned, while var creates a mutable one. Beyond this, the basic types are numbers (Int, Long, Short, Byte, Float, Double), Boolean, Char, and String — every Kotlin type is an object at the language level, even when the JVM represents primitives more efficiently under the hood. String interpolation lets you embed expressions directly with a $ symbol, using curly braces for multi-token expressions. For more advanced formatting, you can compose with multi-line raw strings enclosed in triple quotes, which preserve newlines and most content verbatim while still supporting $ interpolation.

Two universal types anchor the entire hierarchy. Any is the root of all non-nullable types, much like Object in Java, while Any? extends it to include nullable types. Unit is Kotlin's equivalent of void for functions with no meaningful return value, but unlike Java's void, it is a real type with a single value and can be used in generics. At the opposite extreme, Nothing represents computations that never produce a value at all — functions that always throw, infinite loops, or the operand of an Elvis branch that throws. Because Nothing is a subtype of every other type, expressions that throw can appear in any context expecting a value.

For control flow, when is Kotlin's replacement for Java's switch and is considerably more powerful. It can match direct values, ranges (in 1..10), types (is String), and arbitrary predicates, either as a statement or as an expression that returns a value. As an expression, it must be exhaustive — covering every branch or providing an explicit else. Ranges are constructed with .. for inclusive bounds, until for exclusive upper bounds, and downTo for descending iteration, all of which accept an optional step for custom increments. for loops iterate over an iterator over a range, array, collection, or sequence, while while and do-while suit condition-driven loops. To exit a lambda early without breaking out of the surrounding function, you can use a labeled return like return@forEach, which terminates only the current iteration; a custom label like @lit@{ return@lit } handles nested or shadowed cases.

Equality in Kotlin distinguishes structural from referential comparison. The == operator checks structural equality by calling equals(), while === checks referential equality — that is, whether two references point to the very same object in memory. For data classes, the compiler-generated equals implements structural comparison by content, which is why two distinct instances of User("Alice", 30) compare as equal under ==. Smart casting complements this by tracking type checks: after if (obj is String), the compiler treats obj as a non-nullable String inside the branch, removing the need for explicit casts and simplifying chained &&/|| conditions. Taken together, these building blocks give Kotlin a coherent foundation for declaring and reasoning about values.

All chapters
  1. 1Foundations — Types, Variables, and Expressions
  2. 2Null Safety
  3. 3Classes, Objects, and Inheritance
  4. 4Functions, Lambdas, and Scope Functions
  5. 5Properties and Delegation
  6. 6Collections, Sequences, and Strings
  7. 7Coroutines and Flow

Drill it

Reading is not remembering. These come from the Kotlin Programming deck:

Q

What is null safety in Kotlin?

Null safety is a Kotlin feature that eliminates NullPointerException at compile time.By default, variables cannot hold null. You must explicitly declare a type...

Q

How do you declare a nullable type in Kotlin?

Append a ? to the type declaration:var name: String? = nullWithout the ?, the compiler will reject any attempt to assign null.

Q

What is the safe call operator in Kotlin?

The safe call operator ?. allows you to access a property or call a method on a nullable object without risking a NullPointerException:val length = name?.length...

Q

What is the Elvis operator in Kotlin?

The Elvis operator ?: provides a default value when an expression is null:val len = name?.length ?: 0If the left side is null, the right side is used.