Kotlin Fundamentals

Master Kotlin programming with visual diagrams, data flow charts, code examples covering null safety, coroutines, collections, OOP, and best practices

Kotlin is a modern, statically-typed programming language developed by JetBrains that runs on the JVM, officially supported for Android development and backend services.

Kotlin Compilation Architecture

flowchart TB
    A[Kotlin Source .kt] --> B[Kotlin Compiler]
    B --> C[JVM Bytecode .class]
    C --> D[Java Virtual Machine]
    D --> E[Native Execution]
    
    F[Java Interop] --> G[Call Java from Kotlin]
    F --> H[Call Kotlin from Java]
    
    I[Target Platforms] --> J[JVM]
    I --> K[Android]
    I --> L[JavaScript]
    I --> M[Native]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • JVM Compatibility: Compiles to Java bytecode, runs on any JVM
  • 100% Java Interop: Seamlessly call Java libraries and vice versa
  • Multiplatform: Target JVM, Android, JavaScript, and native platforms
  • Static Typing: Type safety with type inference for cleaner code
  • Modern Features: Null safety, coroutines, extension functions built-in

Null Safety System

graph TB
    A[Kotlin Type System] --> B[Non-Nullable Types]
    A --> C[Nullable Types]
    
    B --> B1["String - Cannot be null"]
    B --> B2[Compile-time Safety]
    
    C --> C1["String? - Can be null"]
    C --> C2[Requires Null Checks]
    
    D[Null Operators] --> E["?. Safe Call"]
    D --> F["?: Elvis Operator"]
    D --> G["!! Not-null Assertion"]
    
    E --> E1[Returns null if null]
    F --> F1[Provides default value]
    G --> G1[Throws NPE - Avoid]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • Non-Nullable by Default: Variables cannot be null unless explicitly marked with ?
  • Safe Call (?.): Returns null if receiver is null, prevents NPE
  • Elvis Operator (?:): Provides default value when expression is null
  • Compile-Time Safety: Most null pointer errors caught before runtime
  • Smart Casts: Compiler automatically casts after null checks

Variable Declaration Types

flowchart LR
    A[Variable Types] --> B[val - Immutable]
    A --> C[var - Mutable]
    
    B --> B1[Read-only Reference]
    B --> B2[Like Java final]
    B --> B3[Preferred Choice]
    
    C --> C1[Reassignable]
    C --> C2[Use When Needed]
    
    D[Type Inference] --> E[Automatic Type Detection]
    D --> F[Explicit Type Optional]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • val (Value): Immutable reference, cannot be reassigned after initialization
  • var (Variable): Mutable reference, can be reassigned
  • Type Inference: Compiler infers types from assigned values
  • Best Practice: Prefer val for immutability and thread safety

Data Class Features

graph TB
    A[Data Class] --> B[Auto-Generated Methods]
    
    B --> C[equals and hashCode]
    B --> D[toString]
    B --> E[copy]
    B --> F[componentN]
    
    C --> C1[Value Equality]
    D --> D1[String Representation]
    E --> E1[Create Modified Copy]
    F --> F1[Destructuring]
    
    G[Use Cases] --> H[DTOs]
    G --> I[Models]
    G --> J[Value Objects]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style G fill:#FF9800

Key Points:

  • Automatic Generation: Compiler creates equals, hashCode, toString, copy methods
  • Immutability: Encourages immutable data structures with copy() function
  • Destructuring: Extract properties into variables with componentN functions
  • Concise: Reduces boilerplate compared to Java POJOs

Coroutines Architecture

sequenceDiagram
    participant Main as Main Thread
    participant Scope as Coroutine Scope
    participant Dispatcher
    participant Coroutine
    
    Main->>Scope: launch coroutine
    Scope->>Dispatcher: Select dispatcher
    Dispatcher->>Coroutine: Execute on thread
    Coroutine->>Coroutine: suspend function
    Note over Coroutine: Thread released
    Coroutine->>Coroutine: Resume execution
    Coroutine->>Main: Return result

Key Points:

  • Lightweight Threads: Can run thousands of coroutines on few threads
  • Suspend Functions: Pause execution without blocking threads
  • Structured Concurrency: Automatic cancellation and error handling
  • Dispatchers: Main (UI), IO (network/disk), Default (CPU-intensive)
  • Non-Blocking: Efficient resource usage compared to traditional threads

Collection Operations Flow

flowchart LR
    A[Collection] --> B[Transformation]
    B --> C[map]
    B --> D[filter]
    B --> E[flatMap]
    
    A --> F[Aggregation]
    F --> G[reduce]
    F --> H[fold]
    F --> I[groupBy]
    
    A --> J[Terminal]
    J --> K[toList]
    J --> L[first]
    J --> M[count]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style F fill:#FF9800
    style J fill:#9C27B0

Key Points:

  • Functional Operations: map, filter, reduce for data transformation
  • Lazy Evaluation: Sequences for efficient processing of large collections
  • Immutable by Default: Collection operations return new collections
  • Extension Functions: Rich API for collection manipulation

Extension Functions Pattern

graph TB
    A[Extension Functions] --> B[Add Methods to Classes]
    
    B --> C[Without Inheritance]
    B --> D[Without Modification]
    
    E[Syntax] --> F["fun Type.method()"]
    
    G[Use Cases] --> H[Utility Functions]
    G --> I[DSL Creation]
    G --> J[API Enhancement]
    
    K[Scope] --> L[this refers to receiver]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style E fill:#FF9800
    style G fill:#9C27B0

Key Points:

  • Extend Existing Classes: Add functionality without modifying source code
  • Receiver Type: 'this' refers to the object being extended
  • Static Resolution: Resolved at compile time, not runtime polymorphism
  • Common Pattern: Used extensively in Kotlin standard library

Higher-Order Functions

flowchart TB
    A[Higher-Order Functions] --> B[Accept Functions]
    A --> C[Return Functions]
    
    B --> D[Lambda Parameters]
    C --> E[Function Factories]
    
    F[Common Examples] --> G[map, filter, reduce]
    F --> H[let, apply, run]
    F --> I[also, with]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style F fill:#9C27B0

Key Points:

  • Functions as Parameters: Pass behavior as arguments
  • Lambda Expressions: Concise syntax for anonymous functions
  • Scope Functions: let, apply, run, also, with for object configuration
  • Functional Programming: Enables declarative, composable code

Sealed Classes Hierarchy

graph TB
    A[Sealed Class] --> B[Restricted Hierarchy]
    
    B --> C[Subclass 1]
    B --> D[Subclass 2]
    B --> E[Subclass 3]
    
    F[Benefits] --> G[Exhaustive when]
    F --> H[Type Safety]
    F --> I[Compile-time Checks]
    
    J[Use Cases] --> K[State Management]
    J --> L[Result Types]
    J --> M[UI States]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style F fill:#FF9800
    style J fill:#9C27B0

Key Points:

  • Restricted Inheritance: All subclasses must be in same file/package
  • Exhaustive when: Compiler ensures all cases handled
  • Type-Safe: Better than enums for complex state with data
  • Common Pattern: Result<Success, Error> types in APIs

Object Declaration Pattern

graph LR
    A[Object Keyword] --> B[Singleton]
    A --> C[Companion Object]
    A --> D[Object Expression]
    
    B --> B1[Single Instance]
    C --> C1[Static Members]
    D --> D1[Anonymous Class]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • Singleton: object declaration creates thread-safe singleton
  • Companion Object: Static-like members within classes
  • Object Expression: Anonymous objects for one-time use
  • Lazy Initialization: Objects created on first access

Code Examples

Basic Syntax

// Variables
val name: String = "Kotlin"  // Immutable
var count = 0                // Mutable, type inferred

// Null safety
val nullable: String? = null
val length = nullable?.length ?: 0

// Data class
data class User(val id: Long, val name: String)
val user = User(1, "John")
val updated = user.copy(name = "Jane")

Functions

// Basic function
fun greet(name: String): String {
    return "Hello, $name"
}

// Extension function
fun String.isPalindrome() = this == this.reversed()

// Lambda
val sum = { a: Int, b: Int -> a + b }

Coroutines

// Launch coroutine
GlobalScope.launch {
    val data = fetchData()  // suspend function
    updateUI(data)
}

// Async/await
val result = async { computeValue() }.await()