← 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.
Syntax
kotlin
class ClassName(val property: Type) {
    init {
        require(condition) { "message" }   // runs when created
    }
}

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
// Define a class `Person`
class Person(val name: String, val age: Int) {
    init {
        // Print "Creating person: $name, age $age" to the console, with a trailing newline
        println("Creating person: $name, age $age")
    }
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `person`, set to `Person("Ana", 30)`
    val person = Person("Ana", 30)
    // Print "Created: ${person.name}" to the console, with a trailing newline
    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
// Define a class `Age`
class Age(val value: Int) {
    init {
        require(value >= 0) { "Age cannot be negative" }
    }
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `age`, set to `Age(25)`
    val age = Age(25)
    // Print "Valid age: ${age.value}" to the console, with a trailing newline
    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
// Define a class `Steps`
class Steps {
    // Declare a read-only variable `first`, set to `println("Step 1: property initialized").let { "done" }`
    val first = println("Step 1: property initialized").let { "done" }
    init {
        // Print "Step 2: first init block" to the console, with a trailing newline
        println("Step 2: first init block")
    }
    // Declare a read-only variable `second`, set to `println("Step 3: second property initialized").let { "done" }`
    val second = println("Step 3: second property initialized").let { "done" }
    init {
        // Print "Step 4: second init block" to the console, with a trailing newline
        println("Step 4: second init block")
    }
}

// Entry point: execution of the program starts here
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
// Define a class `Logger`
class Logger(val prefix: String) {
    init {
        // Print "[$prefix] Logger initialized" to the console, with a trailing newline
        println("[$prefix] Logger initialized")
    }

    constructor() : this("DEFAULT") {
        // Print "Secondary constructor body running" to the console, with a trailing newline
        println("Secondary constructor body running")
    }
}

// Entry point: execution of the program starts here
fun main() {
    Logger()
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
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.