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 (likefinal
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! ⬇️😊