100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Kotlin

Object Declarations and Companion Objects in Kotlin

Understand Kotlin's object keyword for singletons and companion objects for class-level, Java-static-like members.

Classes & ObjectsIntermediate9 min readJul 8, 2026
Analogies

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

kotlin
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

kotlin
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

text
Counter: 2
DB ids: 1, 2

Key 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

Was this page helpful?

Topics covered

#Kotlin#KotlinProgrammingStudyNotes#Programming#ObjectDeclarationsAndCompanionObjectsInKotlin#Object#Declarations#Companion#Objects#OOP#StudyNotes#SkillVeris