companion object — mekanisme bahasa Kotlin yang menggantikan kata kunci static dari Java untuk mendeklarasikan anggota statis kelas. Di Kotlin tidak ada static bawaan — sebagai gantinya digunakan deklarasi object dengan pengubah companion di dalam kelas. Menurut JetBrains, 2025, companion object memungkinkan pemanggilan metode dan properti melalui nama kelas, menjadikannya analog lengkap dari anggota statis di ekosistem Java.
Poin Utama
companion object — adalah jenis khusus dari object declaration dalam bahasa Kotlin yang ditandai dengan kata kunci companion. Ini memungkinkan deklarasi anggota yang dimiliki oleh kelas, bukan instance-nya — yaitu anggota statis dalam terminologi Java. Tidak seperti Java di mana static adalah pengubah untuk bidang dan metode individu, di Kotlin anggota statis dikelompokkan dalam satu objek pendamping.
Setiap kelas di Kotlin dapat berisi tepat satu companion object. Anggota object ini dapat diakses melalui nama kelas tanpa membuat instance: MyClass.method(). Sementara itu dari perspektif bytecode, companion object dikompilasi menjadi kelas dalam terpisah, dan metode-metodenya menjadi metode statis dari kelas luar saat menggunakan anotasi @JvmStatic.
Menurut Google I/O 2024, companion object telah menjadi pola utama untuk metode pabrik, konstanta, dan fungsi utilitas dalam aplikasi Android modern di Kotlin. Pengembang memilihnya daripada kelas utilitas dengan fungsi paket, karena companion object mempertahankan hubungan logis dengan kelas pemilik.
Gunakan companion object untuk mengelompokkan konteks statis — konstanta, pabrik, metode pembantu yang secara logis terkait dengan kelas tetapi tidak memerlukan instance.
Sintaksis dasar companion object sederhana: kata kunci companion ditempatkan sebelum deklarasi object di dalam kelas. Jika nama tidak ditentukan, object mendapat nama Companion, yang dapat diakses secara eksplisit atau implisit.
class User {
companion object {
const val TABLE_NAME = "users"
fun create(name: String): User {
return User(name)
}
}
val name: String
constructor(name: String) { this.name = name }
}
// Akses melalui nama kelas
val table = User.TABLE_NAME
val user = User.create("Alice")
Dalam contoh di atas TABLE_NAME dan create() dapat diakses melalui User.TABLE_NAME dan User.create(). Perhatikan pengubah const untuk konstanta primitif — ini menjamin penanaman nilai pada tahap kompilasi, analog dengan Java static final untuk primitif dan String.
Jika companion object tidak memiliki nama, dapat diakses melalui nama otomatis Companion: User.Companion.TABLE_NAME. Dalam praktiknya ini jarang diperlukan, tetapi berguna saat pemanggilan dari kode Java atau saat menggunakan refleksi.
// Kedua panggilan setara
User.create("Bob")
User.Companion.create("Bob")
// Mendapatkan referensi ke companion object
val companion: User.Companion = User
companion object dapat memiliki nama, yang meningkatkan keterbacaan kode dan memungkinkan akses dengan nama yang mudah dipahami. Factory — nama paling umum untuk companion object yang digunakan sebagai pabrik.
class HttpResponse {
companion object Factory {
fun ok(body: String): HttpResponse = HttpResponse(200, body)
fun notFound(): HttpResponse = HttpResponse(404, "Not Found")
fun serverError(): HttpResponse = HttpResponse(500, "Internal Error")
}
}
// Akses melalui nama Factory
val response = HttpResponse.Factory.ok("data")
Companion object bernama membantu mendokumentasikan tujuan anggota statis. Dalam refactoring, nama membuat kode menjadi self-documenting — pengembang langsung melihat bahwa Factory membuat instance HttpResponse.
Kelas hanya dapat berisi satu companion object. Ini adalah perbedaan mendasar dari Java, di mana banyak bidang dan metode statis dapat dideklarasikan tanpa pengelompokan. Jika diperlukan beberapa kelompok logis anggota statis, gunakan deklarasi object bersarang tanpa companion.
Menurut dokumentasi resmi Kotlin (Kotlin Docs, 2025), batasan satu companion object dimotivasi oleh desain bahasa: anggota statis harus terikat erat dengan kelas, dan satu objek pendamping memberikan batas yang jelas dari ikatan ini. Jika anggota statis terlalu banyak — ini adalah sinyal untuk refactoring kelas.
Di Kotlin, antarmuka juga dapat berisi companion object. Ini memungkinkan pendefinisian metode statis dan konstanta langsung di dalam antarmuka, yang tidak mungkin dilakukan di Java. Pendekatan ini sering digunakan untuk mendeklarasikan konstanta yang terkait dengan antarmuka atau metode pabrik.
interface ApiService {
companion object {
const val BASE_URL = "https://api.example.com"
const val TIMEOUT_MS = 5000
fun create(client: OkHttpClient): ApiService =
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.build()
.create(ApiService::class.java)
}
}
Dalam contoh ini BASE_URL, TIMEOUT_MS dan create() milik antarmuka ApiService, bukan implementasinya. Ini nyaman: semua konstanta dan logika pabrik untuk membuat instance layanan API berada di satu tempat — di dalam antarmuka itu sendiri.
Implementasi antarmuka tidak mewarisi anggota companion object — mereka hanya dipanggil melalui nama antarmuka: ApiService.BASE_URL.
Saat memanggil metode companion object dari kode Java, secara default metode tersebut tersedia sebagai metode dari kelas bersarang Companion, bukan sebagai metode statis dari kelas luar. Untuk mengekspornya sebagai metode dan bidang static nyata untuk Java, gunakan anotasi @JvmStatic untuk metode dan @JvmField untuk bidang.
| Anotasi | Penerapan | Hasil di Java |
|---|---|---|
| @JvmStatic | Metode companion object | Metode statis: ClassName.method() |
| @JvmField | Bidang companion object | Bidang statis: ClassName.field |
| const | Primitif dan String | Konstanta inline: kompiler mengganti nilai |
| tanpa anotasi | Metode/bidang default | Companion.method() / Companion.field |
class MathUtils {
companion object {
const val PI = 3.14159
@JvmStatic
fun square(x: Int): Int = x * x
@JvmField
val TAG: String = "MathUtils"
}
}
// Dipanggil di Java sebagai MathUtils.square(5), MathUtils.TAG
Penggunaan @JvmStatic direkomendasikan untuk semua metode publik companion object yang harus dapat diakses dari kode Java. const hanya diterapkan pada tipe primitif dan String — untuk tipe lainnya gunakan @JvmField.
Dalam proyek nyata, companion object digunakan untuk beberapa skenario standar. Metode pabrik — pola paling umum: alih-alih banyak konstruktor dengan tanda tangan berbeda, metode pabrik bernama digunakan di companion object.
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String) : NetworkResult<Nothing>()
companion object {
fun loading<T>(): NetworkResult<T> =
Loading()
}
}
private class Loading<T> : NetworkResult<T>()
companion object di NetworkResult menyediakan metode pabrik loading() yang membuat instance Loading dengan tipe generic yang benar. Tanpa metode ini, Anda harus membuat instance langsung melalui Loading(), yang mengekspos implementasi internal.
Seringkali companion object digunakan untuk menyimpan konstanta spesifik kelas. Konstanta yang dideklarasikan dengan const val ditanamkan pada tahap kompilasi, memberikan overhead nol saat runtime.
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
Pertanyaan yang Sering Diajukan
ordinary object — adalah singleton penuh yang ada secara independen dari kelas. companion object — adalah object di dalam kelas yang anggotanya dipanggil melalui nama kelas luar. Dalam bytecode, companion object menjadi kelas bersarang statis, dan object biasa menjadi kelas singleton otonom.
Tidak, companion object tidak diwariskan oleh subkelas. Jika kelas B mewarisi kelas A, B.method() tidak akan memanggil metode dari companion object kelas A — harus diakses melalui A.method(). Ini sesuai dengan perilaku metode statis di Java.
Secara default — melalui ClassName.Companion.method(). Untuk memanggil sebagai metode statis, tambahkan @JvmStatic ke metode companion object. Untuk bidang gunakan @JvmField atau deklarasikan dengan const val untuk primitif.
Pengembang Kotlin memutuskan untuk meninggalkan static demi companion object untuk pekerjaan yang seragam dengan objek. static di Java melanggar prinsip OOP karena metode statis tidak terikat dengan instance. companion object — adalah objek kelas satu yang dapat diteruskan, diperluas dengan fungsi ekstensi, dan mengimplementasikan antarmuka.
Saat menggunakan const val untuk primitif dan String — overhead nol, nilai ditanamkan dalam bytecode. Untuk metode tidak ada overhead jika metode bukan inline. Dalam kebanyakan kasus, companion object tidak memiliki dampak terukur pada kinerja. Gunakan @JvmStatic hanya untuk API publik yang dipanggil dari Java.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga