Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An initializer block is a designated code block prefixed with the init keyword that executes during the instantiation of a Kotlin class. Because Kotlin’s primary constructor syntax does not allow for an execution body, initializer blocks serve as the execution environment for primary constructor logic.

Syntax

class ClassName(parameter: String) {
    init {
        // Initialization logic executes here
    }
}

Execution Order and Interleaving

Initializer blocks are executed as part of the primary constructor’s lifecycle. If a class contains multiple init blocks and class-level property initializers, they are evaluated sequentially in the exact top-to-bottom order they are declared within the class body.
class InitializationSequence(param: String) {
    // 1. Executes first
    val firstProperty = "Prop 1: $param".also { println(it) }

    // 2. Executes second
    init {
        println("First init block: $param")
    }

    // 3. Executes third
    val secondProperty = "Prop 2".also { println(it) }

    // 4. Executes fourth
    init {
        println("Second init block")
    }
}

Scope and Access Rules

  1. Primary Constructor Parameters: Parameters defined in the primary constructor are directly accessible within any init block in the class.
  2. Property Visibility and Initialization: An init block can access and assign values to properties declared lexically above it. Attempting to read a property declared below the init block results in a compiler error. This error occurs strictly because the property is uninitialized at that point in the execution sequence. Memory for the entire object (including all properties) is allocated on the heap before any initialization logic runs, so the restriction is a safeguard against forward-referencing uninitialized state, not unallocated memory.
class ScopeDemonstration(val id: Int) {
    // Declared, but not yet initialized
    val prefix: String
    
    init {
        // Valid: 'id' is a primary constructor parameter
        // Valid: Assigning a value to 'prefix' declared above this block
        prefix = "ID-"
        println(prefix + id) 
        
        // Invalid: Compiler error. Forward reference to an uninitialized property.
        // println(id.toString() + suffix) 
    }
    
    val suffix = "-END"
}

Relationship with Secondary Constructors

Initializer blocks are guaranteed to execute before the body of any secondary constructor. The exact mechanism depends on whether the class defines a primary constructor:
  1. With a Primary Constructor: If a class has a primary constructor, any secondary constructor must explicitly delegate to it (either directly or indirectly) using this(). The init blocks execute as part of that primary constructor invocation, before the secondary constructor’s body begins.
class ExplicitDelegation(val name: String) {
    init {
        println("1. Init block executes as part of primary constructor")
    }

    // Explicit delegation to the primary constructor via this()
    constructor(value: Int) : this("Name-$value") {
        println("2. Secondary constructor body executes second")
    }
}
  1. Without a Primary Constructor: If a class lacks a primary constructor, secondary constructors must delegate to a superclass constructor (implicitly if the superclass has a no-argument constructor, or explicitly via super(...)), or they can delegate to another secondary constructor within the same class using this(...). The init blocks execute immediately after the superclass constructor finishes, but prior to the execution of the secondary constructor’s body.
open class BaseClass {
    constructor() {
        println("0. Superclass constructor executes")
    }
}

class SuperDelegation : BaseClass {
    init {
        println("1. Init block executes after superclass constructor")
    }

    // Implicit delegation to super() occurs here
    constructor(value: Int) {
        println("2. Secondary constructor body executes second")
    }
    
    // Explicit delegation to another secondary constructor via this()
    constructor(value: String) : this(value.length) {
        println("3. Delegated secondary constructor body executes third")
    }
}
Master Kotlin with Deep Grasping Methodology!Learn More