Deklarasi variabel kadang tidak selalu beriringan dengan inisialisasi langsung. Pada beberapa skenario, kita perlu menunda pemberian nilai hingga kondisi tertentu terpenuhi, atau menunda inisialisasi hingga variabel benar-benar diakses. Kotlin menyediakan beberapa pola deklarasi: inisialisasi langsung dengan tipe eksplisit, pola declare first, assign later, modifier lateinit var, serta delegasi lazy. Pada chapter ini kita akan membedah keempat pola tersebut beserta kapan masing-masing cocok dipakai.
Deklarasi dengan tipe eksplisit #
Bentuk paling sederhana deklarasi variabel adalah val nama: Tipe = nilai. Tipe ditulis setelah nama variabel dengan tanda titik dua. Tipe eksplisit berguna ketika kita ingin membatasi tipe yang lebih spesifik daripada inferensi kompilator.
val nama: String = "Budi"
val umur: Int = 25
val tinggi: Double = 170.5Pola ini cocok ketika nilai literal ambigu atau ketika kita ingin mendokumentasikan tipe secara jelas.
Declare first, assign later #
Kotlin memperbolehkan deklarasi val tanpa inisialisasi asalkan variabel tersebut dijamin diberi nilai tepat sekali sebelum digunakan. Pola ini umum dipakai pada cabang if/when:
val namaPengguna: String
if (tahun >= 2026) {
namaPengguna = "Budi"
} else {
namaPengguna = "Tamu"
}
println(namaPengguna) // BudiKompilator memverifikasi bahwa semua cabang menetapkan nilai ke namaPengguna sebelum digunakan. Bila ada cabang yang tidak menetapkan nilai, kompilasi akan gagal.
lateinit var #
Modifier lateinit var memungkinkan deklarasi variabel non-nullable tanpa nilai awal, dengan janji bahwa nilai akan disematkan sebelum variabel diakses. Pola ini cocok untuk dependency injection, framework testing, atau properti yang diisi oleh kode eksternal.
lateinit var pesanSambutan: String
fun main() {
pesanSambutan = "Halo, Budi!"
println(pesanSambutan)
}Syarat lateinit:
- Hanya untuk
var, bukanval. - Hanya untuk tipe non-primitif (tidak untuk
Int,Double,Boolean). - Hanya untuk tipe non-nullable.
- Akses sebelum diinisialisasi memunculkan
UninitializedPropertyAccessException.
lazy init #
Delegasi lazy menunda inisialisasi hingga pertama kali variabel diakses, lalu meng-cache hasilnya untuk akses berikutnya. lazy cocok untuk objek yang mahal dibuat atau yang mungkin tidak selalu dibutuhkan saat program berjalan.
val konfigurasiDefault: String by lazy {
println(">> Menghitung konfigurasi default...")
"mode=produksi;port=8080"
}Blok lazy dijalankan tepat sekali, pada akses pertama. Akses kedua dan seterusnya mengembalikan nilai yang di-cache, tanpa menjalankan blok lagi. lazy bersifat thread-safe secara default (mode LazyThreadSafetyMode.SYNCHRONIZED).
Contoh lengkap #
Berikut program yang memadukan keempat pola:
lateinit var pesanSambutan: String
val konfigurasiDefault: String by lazy {
println(">> Menghitung konfigurasi default...")
"mode=produksi;port=8080"
}
fun main() {
val tahun: Int = 2026
println("Tahun: $tahun")
val namaPengguna: String
if (tahun >= 2026) {
namaPengguna = "Budi"
} else {
namaPengguna = "Tamu"
}
println("Nama pengguna: $namaPengguna")
pesanSambutan = "Selamat datang di Kotlin, $namaPengguna!"
println(pesanSambutan)
println("Sebelum akses konfigurasi")
println("Konfigurasi: $konfigurasiDefault")
println("Konfigurasi (lagi): $konfigurasiDefault")
}Output yang Dihasilkan:
Tahun: 2026
Nama pengguna: Budi
Selamat datang di Kotlin, Budi!
Sebelum akses konfigurasi
>> Menghitung konfigurasi default...
Konfigurasi: mode=produksi;port=8080
Konfigurasi (lagi): mode=produksi;port=8080Mari kita amati baris-baris penting pada kode di atas:
- Baris 1 (
lateinit var pesanSambutan) — deklarasivartanpa inisialisasi. Kompilator mengizinkan ini karena modifierlateinitmemberi janji eksplisit. - Baris 3-6 (
val konfigurasiDefault by lazy { ... }) — blok lambda akan dieksekusi sekali pada akses pertama. Output">> Menghitung konfigurasi default..."muncul sekali, meskipun variabel diakses dua kali. - Baris 10 (
val tahun: Int = 2026) — deklarasi dengan tipe eksplisit dan inisialisasi langsung. - Baris 13-18 (
val namaPengguna: String; if (...) ... else ...) — pola declare first, assign later. Cabangif/elsemenjaminnamaPenggunaselalu mendapat nilai. - Baris 21 (
pesanSambutan = "...") — inisialisasilateinit varsebelum diakses pada baris 22. - Baris 24-26 (
println("Konfigurasi: $konfigurasiDefault")x2) —lazyhanya menjalankan blok pada akses pertama; akses kedua mengembalikan nilai yang sama tanpa menjalankan blok.
Memilih pola yang tepat #
| Pola | Kapan dipakai | Kapan dihindari |
|---|---|---|
| Tipe eksplisit + inisialisasi | Nilai sudah ada sejak awal | — |
| Declare first, assign later | Nilai bergantung cabang if/when | Hanya satu cabang |
lateinit var | Dependency injection, framework testing | Tipe primitif atau nullable |
lazy init | Objek mahal atau jarang dipakai | Objek ringan yang selalu dipakai |
Referensi Lanjutan #
- Basic types — pengantar tipe dasar Kotlin untuk pola deklarasi dan inisialisasi variabel
- Properties
— dokumentasi properti Kotlin yang menjelaskan
lateinit,by lazy, dan backing field
Pemilihan pola deklarasi yang tepat membuat program lebih aman dan efisien. Setelah memahami pola deklarasi, kita siap melihat bagaimana kompilator Kotlin menentukan tipe variabel tanpa kita menyebutkannya — materi pada chapter Type Inference.