Kotlin Properties: val, var, lateinit, and by lazy Explained 🚀

 

Kotlin Properties: val, var, lateinit, and by lazy Explained 🚀

Imagine you’re building a smart home automation system 🏠.

  • Some devices are always on (like security cameras) 📷 → val (constant, immutable)
  • Some devices can be turned on/off (like lights) 💡 → var (mutable)
  • Some devices need setup before use (like WiFi) 🌐 → lateinit
  • Some devices are activated only when needed (like motion sensors) 🚨 → by lazy

That’s exactly how Kotlin properties work! Let's explore 🚀


📌 In this blog, we’ll explore:

val vs. var (Immutable vs. Mutable)
lateinit (For Late Initialization)
by lazy (For Efficient, One-Time Initialization)
✅ Real-World Examples 🌍


1️⃣ val vs. var: Immutable vs. Mutable Properties

📌 In Kotlin, properties are declared using val or var:

  • val (Immutable): Cannot be changed after initialization (like final in Java).
  • var (Mutable): Can be modified later.

🔹 Example: Car Speed Control 🚗

class Car {
    val brand: String = "Tesla"  // Read-only (cannot change)
    var speed: Int = 0           // Can be modified

    fun accelerate() {
        speed += 10
        println("$brand is now going at $speed km/h")
    }
}

val myCar = Car()
println(myCar.brand)  // Output: Tesla
// myCar.brand = "BMW"  ❌ ERROR: val cannot be reassigned

myCar.accelerate()  // Output: Tesla is now going at 10 km/h

Use val when the value should remain constant and var when it should change.


2️⃣ lateinit: Late Initialization for var Properties

📌 Use lateinit when you don’t want to initialize a variable at declaration.
📌 Works only with var and non-nullable types (String, Int, Boolean are not allowed).

🔹 Example: Setting Up a User Profile 🧑‍💻

class User {
    lateinit var name: String  // Will be initialized later

    fun setName(username: String) {
        name = username
    }

    fun printName() {
        if (::name.isInitialized) {
            println("User name is $name")
        } else {
            println("Name is not initialized yet!")
        }
    }
}

val user = User()
user.printName()  // Output: Name is not initialized yet!

user.setName("Alice")
user.printName()  // Output: User name is Alice

Perfect when you don’t have all the data at object creation.


3️⃣ by lazy: Lazy Initialization for val Properties

📌 by lazy initializes a property only when it’s first accessed (like a lazy-loaded image).
📌 Works only with val (because it’s evaluated only once).

🔹 Example: Loading User Data Only When Needed ⏳

class UserProfile {
    val profileData: String by lazy {
        println("Fetching user profile from database...")
        "User: Alice, Age: 25, Country: USA"
    }
}

val user = UserProfile()
println("User object created!")  
// No output from lazy block yet

println(user.profileData)  
// Output: Fetching user profile from database...
//         User: Alice, Age: 25, Country: USA

println(user.profileData)  // No fetching again!  
// Output: User: Alice, Age: 25, Country: USA

Great for expensive operations (like fetching data from a database or API).


4️⃣ When to Use What? 🤔

Property Type Description Use Case Example
val Immutable, assigned once Constants (e.g., app name, user ID)
var Mutable, can be reassigned User input, real-time data updates
lateinit Deferred initialization for var Dependency injection, lifecycle-based initialization
by lazy Deferred initialization for val Expensive calculations, database/API calls

5️⃣ Real-World Applications 🌍

🔹 1. Managing App Configuration (val)

class AppConfig {
    val appName: String = "MyKotlinApp"
    val version: String = "1.0.0"
}

Use val for constants that never change.


🔹 2. Updating Stock Prices (var)

class Stock {
    var price: Double = 100.0  // Stock price changes dynamically

    fun updatePrice(newPrice: Double) {
        price = newPrice
        println("Stock price updated to $$price")
    }
}

Use var for values that need modification.


🔹 3. User Authentication (lateinit)

class Auth {
    lateinit var token: String  // Token is set after login

    fun login(userToken: String) {
        token = userToken
    }

    fun isAuthenticated(): Boolean {
        return ::token.isInitialized
    }
}

val auth = Auth()
println(auth.isAuthenticated())  // Output: false

auth.login("secure_token_123")
println(auth.isAuthenticated())  // Output: true

Perfect when you need to initialize data later.


🔹 4. Loading Large Images (by lazy)

class ImageLoader {
    val image: String by lazy {
        println("Loading high-resolution image...")
        "Image Data Loaded"
    }
}

val imgLoader = ImageLoader()
println("ImageLoader created!")  
// No image loading yet

println(imgLoader.image)  
// Output: Loading high-resolution image...  
//         Image Data Loaded

println(imgLoader.image)  // Already loaded, no need to fetch again

Optimizes performance by delaying expensive operations.


🔟 Conclusion: Mastering Kotlin Properties 🎯

val → Use for constants that don’t change.
var → Use for mutable values.
lateinit → Use when you need to initialize later (var only).
by lazy → Use when you want to initialize once on first use (val only).

💡 Understanding these helps write cleaner, more efficient Kotlin code! 🚀

💬 Which property type do you use the most? Let me know in the comments! ⬇️😊

Thanks a lot for query or your valuable suggestions related to the topic.

Previous Post Next Post

Contact Form