Introduction
Kotlin has no static keyword. Instead, it offers object declarations to create singletons directly, and companion object to attach class-level members to a class, similar in purpose to Java's static members but implemented as real objects under the hood.
Cricket analogy: Like a league that has no separate 'league office' role but instead designates one club as the permanent governing body (object) and lets any team consult a shared rulebook attached to a franchise (companion object) instead of a standalone static office.
Syntax
object Singleton {
var counter = 0
fun increment() { counter++ }
}
class Database private constructor() {
companion object {
fun connect(): Database = Database()
}
}Explanation
object Singleton defines a class and creates its single instance at the same time, lazily initialized on first access and thread-safe by default. There is no need to write a separate class plus a manual singleton pattern. A companion object is declared inside a class body and its members are accessed through the enclosing class name, e.g. Database.connect(), much like Java static members, even though internally it is a genuine singleton object tied to the class. A companion object can be named, can implement interfaces, and there can be at most one companion object per class.
Cricket analogy: Like a stadium's official scoreboard that's built and switched on the moment the first ball is bowled, not before, an object Singleton initializes lazily on first access, while Stadium.recordScore() called through the ground's name mirrors accessing a companion object via the class name.
Example
object Singleton {
var counter = 0
fun increment() { counter++ }
}
class Database private constructor(val id: Int) {
companion object Factory {
private var nextId = 1
fun connect(): Database = Database(nextId++)
}
}
fun main() {
Singleton.increment()
Singleton.increment()
println("Counter: ${Singleton.counter}")
val db1 = Database.connect()
val db2 = Database.connect()
println("DB ids: ${db1.id}, ${db2.id}")
}Output
Counter: 2
DB ids: 1, 2Key Takeaways
- object declarations create a lazily initialized, thread-safe singleton directly.
- Kotlin has no static keyword; companion object fills that role for class-level members.
- Companion object members are accessed via the class name, e.g. ClassName.member.
- A class can have at most one companion object, which can optionally be named.
- Companion objects can implement interfaces just like regular objects.
- object and companion object are both real singleton instances under the hood, not compiler tricks like Java statics.
Practice what you learned
1. What does an object declaration create in Kotlin?
2. How are companion object members typically accessed?
3. How many companion objects can a single class have?
4. Does Kotlin have a static keyword like Java?
Was this page helpful?
You May Also Like
Classes in Kotlin
Learn how Kotlin classes bundle state and behavior with concise constructor syntax and final-by-default semantics.
Interfaces in Kotlin
Explore how Kotlin interfaces define abstract methods, default implementations, and properties that classes can implement.
Visibility Modifiers in Kotlin
Visibility modifiers control where classes, functions, and properties can be accessed from in Kotlin code.
Sealed Classes in Kotlin
Sealed classes restrict a class hierarchy to a known, closed set of subclasses, enabling exhaustive when checks.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics