16. What is the lateinit modifier in Kotlin ?
In Kotlin, the lateinit modifier is used to defer the initialization of a non-null var property. It tells the compiler:
“I promise to initialize this variable before I use it, but not at the point of declaration.”
Example:
class UserManager {
lateinit var user: User
fun loadUser() {
user = fetchUserFromApi()
}
fun printUser() {
println(user.name) // Safe only if user is initialized
}
}
kotlin.UninitializedPropertyAccessException: lateinit property user has not been initialized
It doesn’t work with:
17. What is the lazy modifier in Kotlin ?
In Kotlin, the lazy modifier is used to initialize a value only when it's first accessed, not when the object is created. This is called lazy initialization, and it's especially useful for improving performance and memory usage when the value is expensive to compute or might not be used at all.
Syntax:
val myValue: String by lazy {
println("Computed!")
"Hello, Lazy!"
}
Example:
fun main() {
val lazyName: String by lazy {
println("Calculating name...")
"Bind the Logic"
}
println("Before accessing lazyName")
println("Name is: $lazyName") // Triggers lazy initialization
println("Again: $lazyName") // Reuses cached value
}
Output:
Before accessing lazyName
Calculating name...
Name is: Bind the Logic
Again: Bind the Logic
Thread Safety Modes
lazy(LazyThreadSafetyMode.SYNCHRONIZED) // Default (thread-safe)
lazy(LazyThreadSafetyMode.PUBLICATION) // Safer for multiple threads
lazy(LazyThreadSafetyMode.NONE) // Not thread-safe (faster)
18. Comparison between lateinit and lazy in Kotlin.
Here’s a clear code comparison between lateinit and lazy in Kotlin, with usage scenarios:
1. Using lateinit (for mutable non-null var)
class DatabaseManager {
lateinit var dbConnection: Connection
fun initConnection() {
dbConnection = createConnection() // manually initialized later
}
fun query() {
if (::dbConnection.isInitialized) {
println("Querying: $dbConnection")
}
}
}
Good for: Android Views, dependency injection, or objects set later.
2. Using lazy (for immutable val, initialized when accessed)
class ConfigLoader {
val config: Map<String, String> by lazy {
println("Loading config...")
loadConfigFromFile()
}
fun showConfig() {
println(config["env"]) // Triggers initialization only on first access
}
}
Good for: Expensive operations (like file I/O or API calls) that should run only when needed.
Key Differences Table :
Feature | lateinit | lazy |
---|---|---|
Type allowed | Only non-null var | Only non-null val |
Primitives support | ❌ Not supported (Int, etc.) | ✅ Supported (via boxing) |
Initialization | Manual (object = ...) | Automatic (runs when accessed) |
Thread-safety | ❌ Not thread-safe | ✅ Optional (LazyThreadSafetyMode) |
Nullability support | ❌ Must be non-null | ❌ Must be non-null |
19. What is extension functions in Kotlin ?
In Kotlin, extension functions let you add new functions to existing classes without modifying their source code or using inheritance.
They’re a powerful way to make code more readable and expressive.
Basic Syntax:
fun ClassName.functionName(params): ReturnType {
// function body
}
Example: Adding a lastChar() function to String
fun String.lastChar(): Char {
return this[this.length - 1]
}
val name = "Kotlin"
println(name.lastChar()) // Output: 'n'
open class Animal
class Dog : Animal()
fun Animal.sound() = "Some sound"
fun Dog.sound() = "Bark"
val animal: Animal = Dog()
println(animal.sound()) // Output: "Some sound", NOT "Bark"
20. What is a sealed class ?
A sealed class in Kotlin is a special kind of class used to restrict class hierarchies — it lets you define a fixed set of subclasses. This is particularly useful for representing state, results, or events in a type-safe and exhaustive way.
Basic Syntax
sealed class Result
class Success(val data: String) : Result()
class Error(val message: String) : Result()
object Loading : Result()
Used in a when Expression
fun handleResult(result: Result) = when (result) {
is Success -> println("Success: ${result.data}")
is Error -> println("Error: ${result.message}")
is Loading -> println("Loading...")
// No `else` needed — compiler knows all cases
}
21. Sealed Class vs Enum vs Abstract Class
Feature | Sealed Class | Enum | Abstract Class |
---|---|---|---|
Subclass flexibility | Full class hierarchy | Fixed values only | Unrestricted |
State/data holding | ✅ Can hold data per subclass | 🚫 Cannot hold complex state | ✅ |
Exhaustive when | ✅ Enforced by compiler | ✅ | ❌ |
File requirement | All subclasses in same file | N/A | N/A |