Kotlin Constructors and Init Blocks
A constructor builds an object from the values passed at creation, and init blocks run extra setup during that build.
Init order follows the body
The first init block, the label initializer, and the second init block print in body order. The output proves the order.
fun makeLabel(): String {
println("property init")
return "counter"
}
class Counter(val start: Int = 0) {
init {
println("first init")
}
val label: String = makeLabel()
init {
println("second init")
}
}
fun main() {
val c = Counter(5)
println(c.label)
println(c.start)
}A secondary constructor runs last
The no-argument constructor delegates to the primary one with the value 99. Its body prints after the init block.
class Counter(val start: Int = 0) {
init {
println("init runs")
}
constructor() : this(99) {
println("secondary body runs")
}
}
fun main() {
val c = Counter()
println(c.start)
}Parameters that become properties
title and pages carry val, so they stay readable on the object. The describe function reads both properties.
class Book(val title: String, val pages: Int) {
fun describe(): String {
return "$title has $pages pages"
}
}
fun main() {
val book = Book("Dune", 412)
println(book.title)
println(book.pages)
println(book.describe())
}A plain parameter during the build
name has no val or var, so it is not a property. The greeting initializer still reads it during the build.
class Greeter(name: String) {
val greeting: String = "Hello, $name"
fun show() {
println(greeting)
}
}
fun main() {
val g = Greeter("Ana")
g.show()
}Example
class Alarm(val hour: Int = 7) {
init {
println("init for $hour")
}
constructor() : this(7) {
println("default alarm set")
}
fun ring(): String {
return "alarm at $hour"
}
}
fun main() {
val a = Alarm()
println(a.ring())
val b = Alarm(9)
println(b.ring())
}Key points
- Primary constructor parameters marked val or var become properties of the class.
- A constructor parameter without val or var can be read while the object is being built.
- Property initializers and init blocks run in the order they appear in the body.
- A secondary constructor begins with the constructor keyword.
- A secondary constructor delegates to the primary constructor with this and its values.
- The secondary constructor body runs after the initializers and init blocks.
- Default values in the primary constructor let callers skip arguments.
In this example, Alarm() takes the secondary constructor, which passes 7 to the primary constructor. The init block prints first, and the secondary body prints after it. Alarm(9) uses the primary constructor directly, so only the init line prints.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Kotlin Playground
Exercise
A class body lists an init block, then a property, then another init block. In what order do they run?