Variabel adalah wadah bernama yang menyimpan nilai selama program berjalan. Kotlin membagi variabel menjadi dua jenis: val untuk variabel read-only dan var untuk variabel yang dapat diubah. Pemilihan antara keduanya menentukan apakah kode kita mudah dipahami dan minim galat, atau justru rentan terhadap kesalahan. Pada chapter ini kita akan membedah perbedaan val dan var, kapan memilih salah satunya, serta jebakan umum terkait imutabilitas compile-time versus runtime.

Apa itu val dan var #

Keyword val mendeklarasikan variabel yang referensinya tidak dapat diubah setelah diinisialisasi. Keyword var mendeklarasikan variabel yang referensinya dapat diubah kapan saja. Kedua keyword ini bersifat eksklusif — sebuah variabel hanya boleh satu di antaranya.

kotlin Sintaks dasar val dan var
val nama: String = "Budi"   // read-only, tidak bisa ditulis ulang
var skor: Int = 10          // mutable, bisa ditulis ulang
skor = 15                   // sah
// nama = "Siti"            // galat kompilasi: val cannot be reassigned

Perbedaan utama antara val dan var dirangkum pada tabel berikut:

Aspekvalvar
Reassign referensiTidak bolehBoleh
Mutasi isi objekBisa (jika objek mutable)Bisa
Default direkomendasikanYaHanya bila perlu
Thread-safe lebih mudahYaTidak otomatis

Mengapa val lebih disarankan #

Variabel val membuat kode lebih mudah diprediksi karena nilai pengikatannya tidak berubah setelah inisialisasi. Pembaca kode tidak perlu mengikuti seluruh jalur eksekusi untuk memastikan nilai akhir sebuah val. Saat kita menggunakan val, kompilator memverifikasi bahwa variabel hanya ditulis sekali, sehingga banyak kelas galat logika tidak akan lolos ke tahap runtime.

Berikut contoh nyata penggunaan val dan var dalam satu program:

kotlin
fun main() {
    val nama: String = "Budi"
    println("Nama: $nama")

    var skor: Int = 10
    println("Skor awal: $skor")
    skor = 15
    println("Skor setelah ditambah: $skor")

    val daftarAnggota = mutableListOf("Budi", "Siti")
    daftarAnggota.add("Dewi")
    println("Daftar anggota: $daftarAnggota")

    val config = buildMap {
        put("host", "localhost")
        put("port", 8080)
    }
    println("Config: $config")
    println("Tipe config: ${config.javaClass.simpleName}")
    println("Tipe daftarAnggota: ${daftarAnggota.javaClass.simpleName}")
}

Output yang Dihasilkan:

text
Nama: Budi
Skor awal: 10
Skor setelah ditambah: 15
Daftar anggota: [Budi, Siti, Dewi]
Config: {host=localhost, port=8080}
Tipe config: MapBuilder
Tipe daftarAnggota: ArrayList

Mari kita amati baris-baris kode di atas:

  1. Baris 2 (val nama: String = "Budi") — variabel nama bersifat read-only; referensi tidak dapat diganti, tetapi karena String sendiri immutable, keseluruhan nilai tidak berubah.
  2. Baris 6 (var skor: Int = 10) — var memungkinkan penulisan ulang. Baris 8 (skor = 15) sah karena var mengizinkan reassign.
  3. Baris 10 (val daftarAnggota = mutableListOf(...)) — val hanya melindungi referensi daftarAnggota, bukan isi list. Kita tetap dapat memanggil daftarAnggota.add(...) karena isi list bersifat mutable.
  4. Baris 14 (val config = buildMap { ... }) — buildMap menghasilkan Map immutable (read-only). Kombinasi val + koleksi immutable memberikan jaminan ganda bahwa nilai tidak akan berubah.

Compile-time vs runtime immutability #

Pada val, jaminan read-only berlaku pada level referensi. Apabila val merujuk ke objek mutable (seperti MutableList), isi objek tetap dapat berubah melalui method yang dimiliki objek tersebut. Inilah perbedaan antara imutabilitas binding (compile-time) dan imutabilitas objek (runtime).

kotlin Contoh val + mutable list
val angka = mutableListOf(1, 2, 3)
angka.add(4)         // sah: isi list berubah, tetapi referensi tetap
// angka = mutableListOf()  // galat: val tidak boleh ditulis ulang
println(angka)      // [1, 2, 3, 4]

Untuk benar-benar membuat data tidak berubah, gunakan tipe koleksi immutable seperti listOf, setOf, atau mapOf. Kombinasi val + koleksi immutable memberi jaminan kuat bahwa data tidak akan dimodifikasi dari referensi tersebut.

Referensi Lanjutan #

  • Basic types — pengantar tipe dasar Kotlin yang menjelaskan deklarasi val dan var sebagai pondasi variabel
  • Properties — dokumentasi properti Kotlin yang merincikan perilaku val (read-only) vs var (mutable)

Dengan memahami batas antara val dan var, kita siap melihat bagaimana cara mendeklarasikan dan menginisialisasi variabel dengan tepat — termasuk pola lateinit dan lazy yang akan kita bahas pada chapter Deklarasi dan Inisialisasi.