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
/**
* 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
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.
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
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.
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
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.
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 :
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
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
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.
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
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.
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.
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 part | Where it is written | Main purpose |
|---|---|---|
| Primary constructor | In the class header after the class name | Defines the main values required to create the object |
| Secondary constructor | Inside the class body using the constructor keyword | Provides an additional construction path and delegates to the primary constructor when one exists |
init block | Inside the class body using the init keyword | Runs initialization logic for every object created through any constructor |
| Property initializer | Inside the class body or directly in the primary constructor | Assigns 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
initexecution happen before the body of the secondary constructor continues. - Using constructor parameters as properties without val or var: A parameter such as
name: Stringis not automatically a property. Useval name: Stringorvar name: Stringwhen 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
initblocks 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
initblock. - The existing Person examples remain intact while the explanation clarifies how
var,this(...), andinitwork. - 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
outputclass.
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.
TutorialKart.com