Kotlin Constructors

Kotlin constructors are special member functions that initialize class instances when objects are created. Unlike Java, Kotlin provides two distinct types of constructors: primary constructors and secondary constructors. The primary constructor is declared in the class header, while secondary constructors are defined within the class body using the constructor keyword.

Every Kotlin class can have one primary constructor and multiple secondary constructors. The primary constructor cannot contain executable code, but you can use init blocks to execute initialization logic. This design makes Kotlin constructors more structured and predictable than their Java counterparts.

Kotlin Primary Constructor

The Kotlin primary constructor is the most concise way to initialize class properties. It’s declared immediately after the class name and becomes part of the class header. Here’s the basic syntax for a primary constructor:

class ClassName constructor(parameter1: Type, parameter2: Type) {  
    // class body  
}  

You can omit the constructor keyword when there are no annotations or visibility modifiers:

class Person(val name: String, var age: Int) {  
    // class body  
}  

Primary Constructor Properties

When you declare parameters in a primary constructor, you can simultaneously declare class properties by using val or var keywords:

  • val creates a read-only property (immutable)
  • var creates a mutable property
class Student(val studentId: String, var grade: Double) {  
    // studentId is read-only, grade is mutable  
}  

Primary Constructor with Default Parameters

Kotlin constructors support default parameters, eliminating the need for multiple constructor overloads:

class GameCharacter(  
    val name: String = "Anonymous",   
    var level: Int = 1,   
    var health: Double = 100.0  
) {  
    // Properties with default values  
}  

This allows flexible object creation:

val character1 = GameCharacter()                          // Uses all defaults  
val character2 = GameCharacter("Warrior")                 // Custom name, default level and health  
val character3 = GameCharacter("Mage", 5)                // Custom name and level  
val character4 = GameCharacter("Archer", 3, 85.5)       // All custom values  

Kotlin Init Blocks

Since primary constructors cannot contain executable code, Kotlin provides init blocks for initialization logic. Init blocks are executed when the class instance is created and have access to primary constructor parameters:

class Vehicle(val brand: String, val model: String) {  
    val vehicleInfo: String  
      
    init {  
        println("Creating vehicle: $brand $model")  
        vehicleInfo = "$brand $model".uppercase()  
          
        // Validation logic  
        require(brand.isNotEmpty()) { "Brand cannot be empty" }  
        require(model.isNotEmpty()) { "Model cannot be empty" }  
    }  
}  

Multiple Init Blocks

A class can have multiple init blocks, and they execute in the order they appear:

class DatabaseConnection(val host: String, val port: Int) {  
    val connectionString: String  
    var isConnected: Boolean = false  
      
    init {  
        println("Initializing database connection...")  
        connectionString = "jdbc:postgresql://$host:$port/database"  
    }  
      
    init {  
        println("Validating connection parameters...")  
        require(port in 1..65535) { "Invalid port number: $port" }  
    }  
      
    init {  
        println("Establishing connection...")  
        isConnected = true  
        println("Connection established successfully!")  
    }  
}  

Kotlin Secondary Constructors

Secondary constructors provide alternative ways to initialize objects when the primary constructor isn’t sufficient. They’re declared using the constructor keyword and must delegate to the primary constructor using the this keyword:

class Rectangle(val width: Double, val height: Double) {  
    val area: Double = width * height  
      
    // Secondary constructor for square  
    constructor(side: Double) : this(side, side) {  
        println("Creating square with side: $side")  
    }  
      
    // Secondary constructor with default dimensions  
    constructor() : this(1.0, 1.0) {  
        println("Creating unit rectangle")  
    }  
}  

Secondary Constructor Delegation Rules

Every secondary constructor must directly or indirectly delegate to the primary constructor:

class BankAccount(val accountNumber: String, var balance: Double) {  
    val accountType: String  
      
    init {  
        accountType = if (balance >= 10000) "Premium" else "Standard"  
        println("Account created: $accountNumber, Type: $accountType")  
    }  
      
    // Secondary constructor with default balance  
    constructor(accountNumber: String) : this(accountNumber, 0.0) {  
        println("Account opened with zero balance")  
    }  
      
    // Secondary constructor delegating to another secondary constructor  
    constructor() : this("AUTO-${System.currentTimeMillis()}") {  
        println("Auto-generated account number")  
    }  
}  

Advanced Kotlin Constructor Features

Constructor Visibility Modifiers

You can control constructor visibility using access modifiers:

class SecureData private constructor(val data: String) {  
    companion object {  
        fun createSecureData(input: String): SecureData? {  
            return if (input.length >= 8) {  
                SecureData(input.reversed())  
            } else {  
                null  
            }  
        }  
    }  
}  

Constructor with Annotations

When using annotations or visibility modifiers, the constructor keyword becomes mandatory:

class ApiClient @Inject constructor(  
    private val httpClient: HttpClient,  
    private val apiKey: String  
) {  
    // class implementation  
}  

Property Initialization in Constructor Body

You can initialize properties that aren’t declared in the primary constructor:

class MusicPlayer(val brand: String) {  
    val supportedFormats: List<String>  
    var volume: Int  
    var isPlaying: Boolean  
      
    init {  
        supportedFormats = listOf("MP3", "FLAC", "WAV", "AAC")  
        volume = 50  
        isPlaying = false  
        println("$brand music player initialized")  
    }  
}  

Full Example: E-commerce Product Class

Here’s a comprehensive example demonstrating all Kotlin constructor concepts:

// Import statements (if needed)  
import java.time.LocalDateTime  
import java.util.*  
  
class Product(  
    val id: String,  
    val name: String,  
    var price: Double,  
    val category: String = "General"  
) {  
    val productCode: String  
    var stock: Int = 0  
    var isAvailable: Boolean = false  
    val createdAt: LocalDateTime  
    val tags: MutableList<String> = mutableListOf()  
      
    init {  
        // Generate product code  
        productCode = "${category.uppercase()}-${id}"  
        createdAt = LocalDateTime.now()  
          
        // Validate price  
        require(price >= 0) { "Price cannot be negative: $price" }  
        require(name.isNotBlank()) { "Product name cannot be blank" }  
          
        println("Product created: $productCode - $name")  
    }  
      
    init {  
        // Set default availability based on category  
        isAvailable = category != "Restricted"  
        println("Product availability set to: $isAvailable")  
    }  
      
    // Secondary constructor for discounted products  
    constructor(  
        id: String,   
        name: String,   
        originalPrice: Double,   
        discountPercent: Double,   
        category: String  
    ) : this(id, name, originalPrice * (1 - discountPercent / 100), category) {  
        tags.add("Discounted")  
        println("Discounted product created with ${discountPercent}% off")  
    }  
      
    // Secondary constructor for limited edition products  
    constructor(  
        id: String,   
        name: String,   
        price: Double,   
        category: String,   
        limitedStock: Int  
    ) : this(id, name, price, category) {  
        stock = limitedStock  
        tags.addAll(listOf("Limited Edition", "Exclusive"))  
        println("Limited edition product created with stock: $limitedStock")  
    }  
      
    // Method to display product information  
    fun displayInfo() {  
        println("""  
            Product Information:  
            Code: $productCode  
            Name: $name  
            Price: $${String.format("%.2f", price)}  
            Category: $category  
            Stock: $stock  
            Available: $isAvailable  
            Tags: ${tags.joinToString(", ")}  
            Created: $createdAt  
        """.trimIndent())  
    }  
      
    // Method to update stock  
    fun updateStock(newStock: Int) {  
        require(newStock >= 0) { "Stock cannot be negative" }  
        stock = newStock  
        isAvailable = stock > 0  
        println("Stock updated to: $stock, Available: $isAvailable")  
    }  
      
    // Method to add tags  
    fun addTag(tag: String) {  
        if (!tags.contains(tag)) {  
            tags.add(tag)  
            println("Tag added: $tag")  
        }  
    }  
}  
  
// Demonstration function  
fun main() {  
    println("=== Kotlin Constructors Demo ===\n")  
      
    // Using primary constructor with default parameter  
    val laptop = Product("LAP001", "Gaming Laptop", 1299.99)  
    laptop.updateStock(15)  
    laptop.addTag("Gaming")  
    laptop.displayInfo()  
      
    println("\n" + "=".repeat(50) + "\n")  
      
    // Using secondary constructor for discounted product  
    val smartphone = Product("PHN001", "Flagship Phone", 999.99, 15.0, "Electronics")  
    smartphone.updateStock(25)  
    smartphone.displayInfo()  
      
    println("\n" + "=".repeat(50) + "\n")  
      
    // Using secondary constructor for limited edition  
    val collectible = Product("COL001", "Vintage Watch", 2499.99, "Luxury", 5)  
    collectible.displayInfo()  
      
    println("\n" + "=".repeat(50) + "\n")  
      
    // Creating products with different parameter combinations  
    val basicProduct = Product("BAS001", "Office Chair", 199.99, "Furniture")  
    basicProduct.updateStock(50)  
      
    val premiumProduct = Product("PRE001", "Executive Desk", 899.99, "Premium")  
    premiumProduct.updateStock(10)  
    premiumProduct.addTag("Premium Quality")  
      
    println("Basic Product: ${basicProduct.name} - ${basicProduct.productCode}")  
    println("Premium Product: ${premiumProduct.name} - ${premiumProduct.productCode}")  
}  

Expected Output:

=== Kotlin Constructors Demo ===  
  
Product created: GENERAL-LAP001 - Gaming Laptop  
Product availability set to: true  
Stock updated to: 15, Available: true  
Tag added: Gaming  
Product Information:  
Code: GENERAL-LAP001  
Name: Gaming Laptop  
Price: $1299.99  
Category: General  
Stock: 15  
Available: true  
Tags: Gaming  
Created: 2025-06-20T10:30:45.123  
  
==================================================  
  
Product created: ELECTRONICS-PHN001 - Flagship Phone  
Product availability set to: true  
Discounted product created with 15.0% off  
Stock updated to: 25, Available: true  
Product Information:  
Code: ELECTRONICS-PHN001  
Name: Flagship Phone  
Price: $849.99  
Category: Electronics  
Stock: 25  
Available: true  
Tags: Discounted  
Created: 2025-06-20T10:30:45.156  
  
==================================================  
  
Product created: LUXURY-COL001 - Vintage Watch  
Product availability set to: true  
Limited edition product created with stock: 5  
Product Information:  
Code: LUXURY-COL001  
Name: Vintage Watch  
Price: $2499.99  
Category: Luxury  
Stock: 5  
Available: true  
Tags: Limited Edition, Exclusive  
Created: 2025-06-20T10:30:45.189  
  
==================================================  
  
Product created: FURNITURE-BAS001 - Office Chair  
Product availability set to: true  
Stock updated to: 50, Available: true  
Product created: PREMIUM-PRE001 - Executive Desk  
Product availability set to: true  
Stock updated to: 10, Available: true  
Tag added: Premium Quality  
Basic Product: Office Chair - FURNITURE-BAS001  
Premium Product: Executive Desk - PREMIUM-PRE001