Kotlin Classes, Primary Constructors, Secondary Constructors, and init Blocks

Similar to Java, Kotlin also provides the concepts of Classes and Constructors. In addition to that Kotlin has two kinds of constructors: Primary and Secondary; and initialization blocks.

In this tutorial, we shall learn about Kotlin Class, Kotlin Constructors – Kotlin Primary Constructor, Kotlin Secondary Constructor, and Kotlin init block with examples.

A Kotlin class is usually declared with its primary constructor in the class header. The class body can then contain properties, functions, initializer blocks, and secondary constructors. Understanding the order in which these parts run is important when you create objects and initialize their state.

Kotlin class declaration with properties and constructors

A class is the base of object oriented programming.. A class is kind of a blue print for type of objects that belong to the class type.

Let us have a quick look into an example of a Kotlin Class to know the placement of Kotlin Constructors.

In the following example, we define a class named Person, with primary and secondary constructors, class variables and class methods.

example.kt

</>
Copy
/**
* Kotlin Class Example and Kotlin Constructor Example
*/
class Person constructor(var name: String, var age: Int){
    // class variables
    var profession: String = "Not Mentioned"

    // secondary constructor
    constructor (name: String, age: Int, profession: String): this(name,age){
        this.profession = profession
    }

    // class method (or routine or function)    
    fun printPersonDetails(){
        println("$name whose profession is $profession, is $age years old.")
    }
}

In this class, name and age are properties declared in the primary constructor because they use var. The property profession is declared inside the class body and receives a default value. The secondary constructor accepts one extra value and then delegates to the primary constructor with this(name, age).

Structure of a Kotlin class header and class body

We shall look at the components that form a class in Kotlin

Kotlin Constructor - Kotlin Secondary Constructor - Kotlin Init Block
Structure of a class in kotlin

As mentioned in the picture above, a class has following three parts :

  • class keyword followed by class_name class Person  – mandatory
  • class_header – Header of the class contains the type parameters and an implicit Kotlin Primary Constructor constructor(var name: String, var age: Int)  – optional
  • Body of Class – contains class variables, Kotlin Secondary Constructors and methods of class. The body of the class is enclosed with curly braces after the header of class – optional

The constructor keyword in the class header is optional when there are no annotations or visibility modifiers on the primary constructor. Therefore, the following shorter form is commonly used.

</>
Copy
class Person(var name: String, var age: Int)

The body is also optional. If the class has no body, the braces can be omitted, as shown above. If the class has properties, functions, init blocks, or secondary constructors, use curly braces for the class body.

Kotlin constructor types used to create class objects

There are two types of Kotlin Constructors. They are Kotlin Primary Constructor and Kotlin Secondary Constructor.

The primary constructor is the usual place to declare required values for an object. Secondary constructors are useful when you need an additional way to create the same class, especially when the alternative construction path has extra setup or must call a different signature.

Kotlin primary constructor in the class header

There could be only one primary constructor for a class in Kotlin. The primary constructor comes right after the class name in the header part of the class.

In the following example, we have defined a class with Primary Constructor is highlighted in the following Example :

example.kt

</>
Copy
fun main(args: Array<String>){
    var person = Person("Suresh",25)
    person.printPersonDetails()
}

/**
* Kotlin Primary Constructor Example - Kotlin Class and Kotlin Constructor
*/
class Person constructor(var name: String, var age: Int){
    var profession: String = "Not Mentioned"
    
    constructor (name: String, age: Int, profession: String): this(name,age){
        this.profession = profession
    }
    
    fun printPersonDetails(){
        println("$name whose profession is $profession, is $age years old.")
    }
}

Output

Suresh whose profession is Not Mentioned, is 25 years old.

In class Person constructor(var name: String, var age: Int), the parameters are also properties because they are declared with var. If you remove var or val, the values are only constructor parameters and are not automatically available as properties outside initialization code.

</>
Copy
class Person(name: String, age: Int) {
    val displayName = name
    val displayAge = age
}

In this syntax-only example, name and age are constructor parameters. The class explicitly stores them in displayName and displayAge.

Visibility modifiers for Kotlin Primary Constructor

The default visibility on the primary constructor is public. However, the visibility can be changed to private, protected or internal. The syntax to change the visibility of Primary constructor using visibility modifier is

</>
Copy
class Person visibility_modifier constructor (var name: String, var age: Int)

When writing actual Kotlin code, place the visibility modifier before the constructor keyword. For example, a private primary constructor is written as follows.

</>
Copy
class Person private constructor(var name: String, var age: Int)

Use this pattern when object creation should be controlled from inside the class, such as through a companion object or factory function.

Kotlin secondary constructor with delegation to primary constructor

Constructors that are written inside the Body of Class are called Secondary constructors.

Secondary Constructor should call primary constructor using this keyword. From the example of Kotlin class already given, the secondary constructor is :

</>
Copy
constructor (name: String, age: Int, profession: String): this(name,age){
    this.profession = profession
}

This secondary constructor takes three variables, but calls primary constructor using : this(name, age)  to set the variables handled by the primary constructor.

In the following example, we have defined a secondary constructor.

example.kt

</>
Copy
fun main(args: Array<String>){
    var person_1 = Person("Suresh",25, "Teaching")
    person_1.printPersonDetails()
}

/**
* Kotlin Secondary Constructor Example - Kotlin Classes and Kotlin Constructors
*/
class Person constructor(var name: String, var age: Int){
    var profession: String = "Not Mentioned"
    
    constructor (name: String, age: Int, profession: String): this(name,age){
        this.profession = profession
    }
    
    fun printPersonDetails(){
        println("$name whose profession is $profession, is $age years old.")
    }
}

Output

Suresh whose profession is Teaching, is 25 years old.

If a class has a primary constructor, every secondary constructor must delegate to it directly or indirectly. Direct delegation uses : this(...) after the secondary constructor parameter list.

Visibility modifiers for Kotlin Secondary Constructor

The default visibility of secondary constructor is public. However, the visibility can be changed to private, protected or internal.

The syntax to provide visibility modifiers for Kotlin Secondary constructor is

</>
Copy
visibility_modifier constructor (var name: String, var age: Int, var profession: String) : this(name, age){

}

The following syntax-only example shows the same idea using a real visibility modifier.

</>
Copy
private constructor(name: String, age: Int, profession: String) : this(name, age) {
    this.profession = profession
}

Kotlin init block for primary constructor initialization logic

If you observe the definition of primary constructor, there is no provision in the header to include some lines code for the primary constructor, except for the declaration of type variables. To fill this void, there is init block. But, care has to be taken that init block is run when the class variable is initialized. Hence, this init block is run for all the constructors irrespective of primary and secondary, and after the execution of primary constructor block. Init block is run with the context of primary constructor.

An init block is commonly used for validation, derived property setup, or logging that should happen whenever an object is created. It can access primary constructor parameters and properties declared before it in the class body.

An example Kotlin program to demonstrate the working of Kotlin init block is given below :

example.kt

</>
Copy
fun main(args: Array<String>){
    var person_0 = Person("Ranjan",21)
    person_0.printPersonDetails()
    var person_1 = Person("Suresh",25, "Teaching")
    person_1.printPersonDetails()
}

/**
* Kotlin Init Example
*/
class Person constructor(var name: String, var age: Int){
    var profession: String = "Not Mentioned"
    // initializer block is run during the initialization of class object, after executing constructor
    init{
        println("$name's details are being held in this class object.")
    }
    
    constructor (name: String, age: Int, profession: String): this(name,age){
        this.profession = profession
    }
    
    fun printPersonDetails(){
        println("$name whose profession is $profession, is $age years old.")
    }
}

Output

Ranjan's details are being held in this class object.
Ranjan whose profession is Not Mentioned, is 21 years old.
Suresh's details are being held in this class object.
Suresh whose profession is Teaching, is 25 years old.

Notice the order in the output. When Person("Suresh", 25, "Teaching") is called, Kotlin first delegates from the secondary constructor to the primary constructor, then runs property initializers and init blocks, and then continues with the body of the secondary constructor where profession is changed to Teaching.

Order of execution for Kotlin property initializers and init blocks

Property initializers and init blocks run in the order in which they appear in the class body. The primary constructor parameters are available to them. This small example makes the execution order visible.

</>
Copy
class Sample(name: String) {
    val first = "First property for $name"

    init {
        println(first)
        println("First init block")
    }

    val second = "Second property"

    init {
        println(second)
        println("Second init block")
    }
}

fun main() {
    Sample("Kotlin")
}
First property for Kotlin
First init block
Second property
Second init block

This order matters when one property depends on another. Keep initialization simple and place dependent properties after the values they need.

Default constructor values instead of extra Kotlin secondary constructors

In many Kotlin classes, default parameter values reduce the need for secondary constructors. The earlier Person example can be written with a single primary constructor by giving profession a default value.

</>
Copy
class Person(
    var name: String,
    var age: Int,
    var profession: String = "Not Mentioned"
) {
    fun printPersonDetails() {
        println("$name whose profession is $profession, is $age years old.")
    }
}

fun main() {
    val person1 = Person("Ranjan", 21)
    val person2 = Person("Suresh", 25, "Teaching")

    person1.printPersonDetails()
    person2.printPersonDetails()
}
Ranjan whose profession is Not Mentioned, is 21 years old.
Suresh whose profession is Teaching, is 25 years old.

This form is shorter and easier to maintain when the secondary constructor only supplies optional values. Use a secondary constructor when it represents a genuinely different way to build the object.

Primary constructor, secondary constructor, and init block comparison

Kotlin class partWhere it is writtenMain purpose
Primary constructorIn the class header after the class nameDefines the main values required to create the object
Secondary constructorInside the class body using the constructor keywordProvides an additional construction path and delegates to the primary constructor when one exists
init blockInside the class body using the init keywordRuns initialization logic for every object created through any constructor
Property initializerInside the class body or directly in the primary constructorAssigns an initial value to a class property

Common mistakes with Kotlin constructors and init blocks

  • Forgetting constructor delegation: If a class has a primary constructor, each secondary constructor must call it directly or indirectly using this(...).
  • Assuming secondary constructor code runs before init: Delegation to the primary constructor and init execution happen before the body of the secondary constructor continues.
  • Using constructor parameters as properties without val or var: A parameter such as name: String is not automatically a property. Use val name: String or var name: String when it must be stored as part of the object.
  • Creating unnecessary secondary constructors: Prefer default parameter values when the only difference is an optional argument.
  • Placing dependent initialization too early: Property initializers and init blocks run in the order written, so a value should not depend on another property declared later.

Official Kotlin references for classes and constructors

For additional details, refer to the official Kotlin documentation on classes, constructors, and initializer blocks. You can also continue with related TutorialKart lessons from the Kotlin Tutorial.

Frequently asked questions on Kotlin constructors and init blocks

What is the difference between a Kotlin primary constructor and an init block?

The primary constructor declares the main parameters required to create an object. An init block contains executable initialization code that runs when the object is created. The init block can use primary constructor parameters.

Can a Kotlin class have more than one primary constructor?

No. A Kotlin class can have only one primary constructor. It can have multiple secondary constructors inside the class body when additional construction paths are needed.

Does a Kotlin secondary constructor always need to call the primary constructor?

If the class has a primary constructor, a secondary constructor must delegate to it directly or indirectly using this(...). If the class has no primary constructor, secondary constructors do not have a primary constructor to delegate to.

When should I use default values instead of a secondary constructor in Kotlin?

Use default values when the extra constructor only supplies optional values. Use a secondary constructor when object creation needs a separate path, additional conversion, or setup that cannot be expressed cleanly with default parameters.

In what order do Kotlin constructors and init blocks run?

When an object is created through a secondary constructor, Kotlin first delegates to the primary constructor. Then property initializers and init blocks run in their written order. After that, the body of the secondary constructor continues.

Editorial QA checklist for Kotlin classes and constructors

  • The tutorial distinguishes a class header, primary constructor, class body, secondary constructor, property initializer, and init block.
  • The existing Person examples remain intact while the explanation clarifies how var, this(...), and init work.
  • The page explains the execution order for secondary constructor delegation, property initializers, and initializer blocks.
  • The tutorial warns when default parameter values are cleaner than an additional secondary constructor.
  • New code examples use PrismJS-compatible Kotlin classes, and output-only blocks use the output class.

Conclusion: Kotlin class construction flow

In this Kotlin Tutorial, we have learned the structure of a class in Kotlin with an example, also the types of Kotlin Constructors we have for a class: primary constructor and secondary constructor, and the role of init block in aiding primary constructor.

A primary constructor defines the main way to create a Kotlin object. A secondary constructor offers an additional creation path, and an init block runs shared initialization logic for every object. When optional values are enough, default constructor parameters are often simpler than writing another constructor.