object in Kotlin: syntax and practical use of singleton objects

Author: IT Sectr Published: 2026-06-21 Reading time: 9 min

object in Kotlin is a declarative way to create a singleton object with lazy initialization and thread safety by default. The object keyword replaces an entire class with a single instance and is used for declaring singletons, companion objects, anonymous objects, and static utilities. According to JetBrains Kotlin Documentation (2026), object declaration is the simplest and safest way to implement a singleton in the JVM world.

Key Takeaways

  • object — keyword for declaring a singleton class with a single instance
  • Lazy initialization — object is created on first access, not at class load time
  • Companion object — analog of static members in Kotlin (no static keyword)
  • Object expression — anonymous object for overriding methods on the fly
  • Thread safety — object initialization is guaranteed thread-safe

What is object in Kotlin?

object in Kotlin is a special declaration form that simultaneously defines a class and creates its single instance (singleton). It is a hybrid of class declaration and instance creation in one construct.

In Java, creating a singleton requires a private constructor, a static field, a getInstance method, and thread safety handling. Kotlin’s object does this in a single line of code: object MySingleton { }. The compiler automatically generates thread-safe lazy initialization using the static initializer mechanism in JVM bytecode.

According to the Kotlin Language Specification (2026), object declaration compiles into a final class with a private constructor and a static INSTANCE field initialized in a static block. This guarantees initialization atomicity at the JVM level.

Singleton objects (object declaration)

Object declaration (singleton object) is declared using the object keyword followed by a name. The object body can contain properties, methods, init blocks, and inherit other classes or interfaces.

kotlin
object DatabaseManager {
    private val connection: String = "jdbc:postgresql://localhost:5432/app"
    
    fun query(sql: String): List<Map<String, Any>> {
        // executing the query
        return emptyList()
    }
}

// Usage
DatabaseManager.query("SELECT * FROM users")

Initialization of DatabaseManager happens on first access — lazily and thread-safely. No additional synchronization code is required.

Inheritance for object

Object can inherit regular classes and interfaces. This allows using object as an implementation of an abstract class or interface with a single instance.

kotlin
interface Logger {
    fun log(message: String)
}

object ConsoleLogger : Logger {
    override fun log(message: String) {
        println("[LOG] $message")
    }
}

Companion object

companion object is a special object declared inside a class with the companion keyword. It replaces static members in Kotlin since the language has no static keyword.

kotlin
class ApiClient {
    companion object {
        private const val BASE_URL = "https://api.example.com"
        
        fun create(): ApiClient {
            return ApiClient()
        }
    }
}

// Calling without creating an ApiClient instance
val client = ApiClient.create()

Companion object can have a name (default is Companion), implement interfaces, and be extended via extension functions. Unlike static methods in Java, a companion object is a full-fledged object that can be passed as an argument or stored in a variable.

According to Kotlin Best Practices (2026), companion object is used for factory methods, constants, and static utilities related to the class. It is recommended to avoid excessive use of companion object — for unrelated utilities, top-level functions are preferable.

@JvmStatic annotation

For Java compatibility, companion object methods can be annotated with @JvmStatic. This generates a real static method in JVM bytecode, accessible from Java code without the Companion syntax.

Object expressions (anonymous objects)

Object expression is an anonymous object created on the spot to override methods of a class or interface without declaring a separate named class.

kotlin
val handler = object : Runnable {
    override fun run() {
        println("Task executed")
    }
}

thread(handler)

Object expressions differ from object declarations in that they create a new instance each time they are executed. They are not singletons and have no name. Anonymous objects can capture variables from their closure, just like lambdas.

Unlike Java, where anonymous classes can inherit only one type, Kotlin’s object expression can inherit multiple types at once.

kotlin
interface Clickable {
    fun click()
}

abstract class View {
    abstract fun render()
}

val button = object : View(), Clickable {
    override fun render() = println("Rendering button")
    override fun click() = println("Button clicked")
}

Practical use cases

Object is one of the most versatile Kotlin constructs, used in many scenarios.

Repository singletons

In Android projects, object is often used for declaring a Repository where multiple instances are not needed. A single instance ensures data consistency.

kotlin
object UserRepository {
    fun getUser(id: Int): User? {
        // getting the user
        return null
    }
}

Factory methods via companion object

Companion object with factory methods is an alternative to multiple constructors. Named factory methods make code self-documenting.

kotlin
data class GsonParser {
    companion object {
        fun create(): GsonParser = GsonParser()
        fun createPretty(): GsonParser = GsonParser()
    }
}

Constants and enumerations

Object can serve as a container for constants, replacing static final fields in Java. Object supports inheritance, which allows creating configuration hierarchies.

According to the Kotlin Standard Library (2026), object declaration is the most performant way to create a singleton in Kotlin, outperforming double-checked locking implementations and comparable to enum singleton in Java.

Frequently Asked Questions

How does object differ from a regular class?

Object simultaneously declares a class and creates its single instance. A regular class can have multiple instances created via a constructor.

When is an object declaration initialized?

Lazily — on the first access to the object. Until then, no memory is allocated and the code in the init block is not executed.

Can an object have a constructor?

No, object cannot have an explicit constructor. Initialization is performed in the init block, which is called once on first access to the object.

How is companion object different from a regular object?

companion object is an object declared inside a class. Its members are accessible through the class name without creating an instance, replacing Java’s static members.

Are object declarations safe in a multithreaded environment?

Yes, object initialization is completely thread-safe thanks to the JVM static initializer. No additional synchronization is required.

Summary

  • object — declarative singleton with lazy and thread-safe initialization
  • companion object — static members in Kotlin, factory methods, constants
  • Object expression — anonymous objects on the spot with variable capture from closure
  • Inheritance — object can inherit classes and interfaces, including multiple types
  • Performance — initialization via JVM static initializer, no double-checked locking overhead
  • Usage — singleton services, repository, constants, factories, listener adapters
  • Limitations — no explicit constructor, single instance per JVM

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also