← Back to Kotlin Course | Chapter 6: Classes & Objects | Lesson 4 of 7

The init Block

An init block is a piece of setup code that runs automatically right when a new object is being built, before anyone else gets to use it.

Running Setup Code with init

An init block contains code that runs immediately when an instance is created, useful for validation or setup logic that goes beyond a simple property assignment.

Example: Running Setup Code with init

markup
class Person(val name: String, val age: Int) {
    init {
        println("Creating person: $name, age $age")
    }
}

fun main() {
    val person = Person("Ana", 30)
    println("Created: ${person.name}")
}

Validating Constructor Arguments

A common use of init is to validate the values passed to the primary constructor, throwing an exception immediately if something is invalid.

Example: Validating Constructor Arguments

markup
class Age(val value: Int) {
    init {
        require(value >= 0) { "Age cannot be negative" }
    }
}

fun main() {
    val age = Age(25)
    println("Valid age: ${age.value}")
}

Multiple init Blocks and Property Order

A class can contain more than one init block, and Kotlin runs them, interleaved with property initializers, in the exact top-to-bottom order they appear in the class body.

Example: Multiple init Blocks and Property Order

markup
class Steps {
    val first = println("Step 1: property initialized").let { "done" }
    init {
        println("Step 2: first init block")
    }
    val second = println("Step 3: second property initialized").let { "done" }
    init {
        println("Step 4: second init block")
    }
}

fun main() {
    Steps()
}

init Blocks with Secondary Constructors

Because every secondary constructor must delegate to the primary constructor, init blocks always run before a secondary constructor's own body executes.

Example: init Blocks with Secondary Constructors

markup
class Logger(val prefix: String) {
    init {
        println("[$prefix] Logger initialized")
    }

    constructor() : this("DEFAULT") {
        println("Secondary constructor body running")
    }
}

fun main() {
    Logger()
}
Common Mistakes
  1. Forgetting that multiple init blocks and property initializers run in the exact order they are written in the class body, not in a separate fixed order.
  2. Putting logic in init that depends on a secondary constructor's parameter, forgetting init blocks run before secondary constructor bodies (but after the primary constructor's own delegation).
  3. Duplicating validation logic in every secondary constructor instead of placing shared checks in an init block once.
Chapter Summary
  • init blocks run as part of instance creation, in the order they appear alongside property initializers in the class body.
  • A class can have multiple init blocks, and they execute top-to-bottom interleaved with property initialization.
  • init blocks can access primary constructor parameters directly, since they run as part of primary construction.
  • Validation logic common to every instance is often placed in an init block rather than repeated per constructor.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.