Kotlin logoKotlin INTERMEDIATE

Kotlin

Modern, concise, and safe programming language for JVM and Android development

15 min read

Getting Started

Kotlin basics and fundamentals

Variables & Types

Variable declarations and basic types

javascript
💡 Use val by default, var only when mutability is needed
⚡ Type inference makes explicit types often unnecessary
📌 const val for compile-time constants, val for runtime constants
🟢 lateinit for non-null properties initialized after construction

String Templates

String interpolation and manipulation

javascript
💡 Use $ for simple variables, ${} for expressions
⚡ Triple quotes for multiline strings without escaping
📌 trimMargin() removes leading whitespace with | delimiter
🟢 buildString is efficient for complex string construction

Null Safety

Kotlin null safety system

Nullable Types

Working with nullable types safely

javascript
💡 ? makes a type nullable, safe call ?. prevents NPE
⚡ Elvis operator ?: provides default for null values
📌 Avoid !! (not-null assertion) - it defeats null safety
🟢 Smart casts eliminate need for explicit casting after null check

Null Safety Patterns

Advanced null handling patterns

javascript
💡 Scoped functions (let, run, also) handle nullables elegantly
⚡ takeIf/takeUnless return value or null based on predicate
📌 Delegates.notNull() for properties initialized after construction
🟢 Contracts tell compiler about null state after function calls

Functions

Function declarations and features

Function Basics

Function syntax and parameters

javascript
💡 Single expression functions use = instead of braces
⚡ Named arguments improve readability and allow skipping defaults
📌 tailrec optimizes tail recursive functions to loops
🟢 Infix functions allow natural DSL-like syntax

Higher-Order Functions

Functions as parameters and lambdas

javascript
💡 Lambdas are functions defined with { } syntax
⚡ inline functions reduce overhead by inlining at call site
📌 crossinline prevents non-local returns in lambdas
🟢 Function with receiver enables DSL-style APIs

Classes & Objects

Object-oriented programming in Kotlin

Classes

Class declarations and constructors

javascript
💡 Primary constructor is part of class header
⚡ init blocks run during instance initialization
📌 Use field keyword to access backing field in setters
🟢 Class delegation with by keyword promotes composition

Inheritance

Class inheritance and polymorphism

javascript
💡 Classes and members are final by default, use open to allow inheritance
⚡ Sealed classes enable exhaustive when expressions
📌 Interfaces can have default implementations
🟢 Use abstract classes for shared state, interfaces for contracts

Data Classes & Objects

Data classes, objects, and companions

Data Classes

Classes for holding data

javascript
💡 Data classes auto-generate equals(), hashCode(), toString(), copy()
⚡ Destructuring declarations use componentN() functions
📌 Only properties in primary constructor are used in generated methods
🟢 Use copy() to create modified instances immutably

Objects & Companions

Singleton objects and companion objects

javascript
💡 object creates a singleton with thread-safe lazy initialization
⚡ Companion objects are per-class singletons for factory methods
📌 @JvmStatic makes companion methods static in Java
🟢 Object expressions create anonymous classes on the fly

Collections

Lists, Sets, Maps and operations

Collection Types

Lists, Sets, and Maps

javascript
💡 Default collections are immutable, use mutable* for mutability
⚡ to infix function creates Pair for map entries
📌 buildList/buildMap efficiently create immutable collections
🟢 Arrays have fixed size, Lists can be resized (if mutable)

Collection Operations

Transformations and aggregations

javascript
💡 Collection operations return new collections (immutable)
⚡ Use sequences for lazy evaluation of large collections
📌 fold provides initial value, reduce uses first element
🟢 partition splits collection into two based on predicate

Control Flow

Conditionals and loops

Conditionals

if, when, and conditional expressions

javascript
💡 if and when are expressions that return values
⚡ when without argument acts like if-else chain
📌 Sealed classes with when provide exhaustive checks
🟢 Smart casts work in when branches after type checks

Loops

for, while, and loop control

javascript
💡 Ranges (1..5) and progressions (step, downTo) control iteration
⚡ withIndex() provides index-value pairs for iteration
📌 Labels allow breaking/continuing outer loops
🟢 forEach is inline, so return exits the enclosing function

Extensions

Extension functions and properties

Extension Functions

Adding functions to existing types

javascript
💡 Extensions add functions without modifying original class
⚡ Extensions are resolved statically, not polymorphically
📌 Member functions always win over extensions
🟢 Can extend nullable types with null-safe operations

Scope Functions

let, run, with, apply, also

javascript
💡 let/also use it, run/apply/with use this
⚡ let/run/with return result, apply/also return receiver
📌 Use let for null checks and transformations
🟢 Use apply for object configuration, also for side effects

Coroutines

Asynchronous programming with coroutines

Coroutine Basics

Launching and managing coroutines

javascript
💡 suspend functions can call other suspend functions
⚡ async for concurrent execution, await for results
📌 Structured concurrency ensures child coroutines complete
🟢 Use runBlocking only in main or tests

Coroutine Context

Dispatchers and coroutine context

javascript
💡 Dispatchers determine which thread coroutines run on
⚡ Flow is cold (starts on collect), Channel is hot
📌 withContext switches context without creating new coroutine
🟢 StateFlow holds state, SharedFlow broadcasts events

Generics

Generic types and variance

Generic Classes & Functions

Type parameters and constraints

javascript
💡 out for covariance (producers), in for contravariance (consumers)
⚡ reified allows using type parameter in is checks
📌 Star projection (*) represents unknown type argument
🟢 Use where clause for multiple type constraints

Delegation

Class and property delegation

Delegation Patterns

Class delegation and delegated properties

javascript
💡 by keyword enables delegation for classes and properties
⚡ lazy delegates compute value only once on first access
📌 observable and vetoable track/validate property changes
🟢 Map delegation useful for dynamic property storage

DSL Building

Creating domain-specific languages

DSL Construction

Building type-safe DSLs

javascript
💡 Lambda with receiver enables DSL syntax
⚡ @DslMarker prevents scope leaking in nested DSLs
📌 Infix functions create natural language-like APIs
🟢 Type-safe builders provide compile-time validation

Annotations & Reflection

Custom annotations and reflection

Annotations

Creating and using annotations

javascript
💡 @Target specifies where annotation can be used
⚡ @Retention determines if annotation is available at runtime
📌 Reflection requires kotlin-reflect dependency
🟢 Use @Jvm* annotations for Java interoperability

Interoperability

Java interop and platform types

Java Interop

Calling Java from Kotlin and vice versa

javascript
💡 Platform types (!) can be null, handle carefully
⚡ @JvmStatic makes companion members static in Java
📌 SAM conversion works for Java functional interfaces
🟢 Use @JvmOverloads for Java-friendly default parameters

Advanced Features

Inline classes, contracts, and more

Inline & Value Classes

Performance optimizations

javascript
💡 inline eliminates function call overhead
⚡ Value classes wrap primitives without runtime overhead
📌 Contracts tell compiler about function behavior
🟢 Type aliases improve code readability