In Kotlin, constructors and init blocks provide a structured way to initialize objects and perform setup tasks. Kotlin simplifies object creation by supporting primary and secondary constructors along with initialization blocks.
Constructors and init blocks help in setting up the initial state of objects:
The primary constructor is a concise way to initialize a class. It is defined in the class header:
class Person(val name: String, var age: Int)
The init block is executed when the object is created and can contain initialization logic:
class Person(val name: String, var age: Int) {
init {
println("Person object created: $name, Age: $age")
}
}
Example:
fun main() {
val person = Person("Alice", 25)
}
Output:
Person object created: Alice, Age: 25
Secondary constructors allow multiple ways to initialize a class. They are defined inside the class body using the constructor keyword:
class Person {
var name: String
var age: Int
constructor(name: String) {
this.name = name
this.age = 0
}
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
}
Example:
fun main() {
val person1 = Person("Bob") // Uses first secondary constructor
val person2 = Person("Charlie", 30) // Uses second secondary constructor
println("${person1.name}, ${person1.age}") // Bob, 0
println("${person2.name}, ${person2.age}") // Charlie, 30
}
You can combine primary constructors, secondary constructors, and init blocks to handle complex initialization:
class Person(val name: String, var age: Int) {
init {
println("Init block: $name, Age: $age")
if(age < 0) age = 0
}
constructor(name: String) : this(name, 0) {
println("Secondary constructor called for $name")
}
}
Example:
fun main() {
val person1 = Person("David", 28) // Primary constructor called
val person2 = Person("Eve") // Secondary constructor called
}
Output:
Init block: David, Age: 28
Init block: Eve, Age: 0
Secondary constructor called for Eve
Here’s the order when an object is created:
init blocks execute in the order they appear in the class.If you don’t delegate to the primary constructor, the secondary constructor runs directly and init blocks are not executed.
init block runs immediately after the primary constructor is called, before any secondary constructor logic.: this(...) in secondary constructors? Int, false for Boolean, and null for nullable references).init blocks) is run unless explicitly defined.
class Person {
var name: String? = null
var age: Int = 0
}
fun main() {
val person = Person() // Uses compiler-generated default constructor
println("Name: ${person.name}, Age: ${person.age}")
}
Output:
Name: null, Age: 0
Explanation:public no-argument constructor.name and age are initialized with default values because no constructor overrides them.
public class Person {
String name;
int age;
// Default constructor is auto-generated by compiler
}
public class Main {
public static void main(String[] args) {
Person p = new Person(); // Uses compiler-provided default constructor
System.out.println("Name: " + p.name + ", Age: " + p.age);
}
}
Output:
Name: null, Age: 0