Beberapa nilai tidak pernah berubah selama program berjalan: konstanta matematika seperti PI, batas maksimum pengguna, atau nama aplikasi. Untuk nilai-nilai ini, Kotlin menyediakan deklarasi const val yang mengunci nilai pada saat kompilasi dan menyematkannya langsung ke bytecode. Berbeda dari val biasa yang dievaluasi saat runtime, const val tidak memiliki overhead inisialisasi. Pada chapter ini kita akan membedah deklarasi const val, syarat tipe yang diperbolehkan, serta perbedaan dengan val runtime.
Apa itu const val #
Modifier const dipakai bersama val untuk mendeklarasikan konstanta compile-time. Nilai konstanta harus dapat dievaluasi sepenuhnya saat kompilasi — tidak boleh bergantung pada hasil function call, property non-const, atau data runtime.
const val PI: Double = 3.141592653589793
const val NAMA_APLIKASI: String = "BelajarKotlin"
const val VERSI: Int = 1
const val MAX_PENGGUNA: Int = 100Setelah dikompilasi, nilai konstanta disisipkan langsung ke bytecode. Saat dipakai, tidak ada lookup property runtime — performa setara dengan literal.
Syarat const val #
Tidak semua val dapat menjadi const val. Syarat berikut wajib dipenuhi:
| Syarat | Keterangan |
|---|---|
Tipe wajib String atau primitive | String, Int, Long, Float, Double, Byte, Short, Boolean, Char |
| Nilai harus literal atau ekspresi konstanta | Tidak boleh hasil function call atau property runtime |
Lokasi: top-level atau object/companion object | Tidak boleh di local variable atau instance property |
Tidak boleh var | const hanya untuk val |
// Sah
const val PI: Double = 3.14
const val NAMA: String = "Kotlin"
const val MAX: Int = 100
const val HEX: Int = 0xFF
const val BITS: Int = 8 * 4 // ekspresi konstanta
const val NAMA_LEN: Int = NAMA.length // ekspresi konstanta dari konstanta lain
// Tidak sah
// const val SEKARANG: Long = System.currentTimeMillis() // bukan konstanta
// const val DAFTAR: List<Int> = listOf(1, 2, 3) // List bukan primitive
// fun foo() {
// const val X: Int = 5 // const tidak boleh di local
// }Lokasi const val #
const val hanya boleh dideklarasikan di:
- Top-level — di luar class/function, dalam file
.kt. object— singleton Kotlin.companion objectdi dalam class.
Tidak boleh di local variable atau instance property non-object.
// Top-level
const val APP_NAME: String = "BelajarKotlin"
object Konfigurasi {
const val HOST: String = "localhost"
const val PORT: Int = 8080
}
class Lingkaran(val radius: Double) {
companion object {
const val PI: Double = 3.141592653589793
}
fun luas(): Double = PI * radius * radius // akses: Lingkaran.PI atau PI di dalam
}Demonstrasi const val #
Berikut program lengkap yang membandingkan const val dengan val biasa:
const val PI: Double = 3.141592653589793
const val NAMA_APLIKASI: String = "BelajarKotlin"
const val VERSI: Int = 1
const val MAX_PENGGUNA: Int = 100
object Konfigurasi {
const val HOST: String = "localhost"
const val PORT: Int = 8080
const val TIMEOUT_MS: Int = 5000
}
val waktuMulai: Long = 1_700_000_000_000_000_000L
fun main() {
println("=== Konstanta top-level (const val) ===")
println("PI = $PI")
println("NAMA_APLIKASI= $NAMA_APLIKASI")
println("VERSI = $VERSI")
println("MAX_PENGGUNA = $MAX_PENGGUNA")
println()
println("=== Konstanta di object (const val) ===")
println("HOST = ${Konfigurasi.HOST}")
println("PORT = ${Konfigurasi.PORT}")
println("TIMEOUT_MS = ${Konfigurasi.TIMEOUT_MS}")
println()
println("=== Property val biasa (runtime) ===")
val waktuAksesPertama: Long = 1_700_000_000_000_001_234L
println("waktuMulai (val) = $waktuMulai")
println("waktuAksesPertama (val) = $waktuAksesPertama")
println("Selisih = ${waktuAksesPertama - waktuMulai} ns")
println()
val lingkaran = Lingkaran(5.0)
println("Lingkaran radius = ${lingkaran.radius}")
println("Luas lingkaran = ${lingkaran.luas()}")
println("Keliling = ${lingkaran.keliling()}")
println()
println("=== Demonstriasi inline const ===")
println("Maks pengguna x 2 = ${MAX_PENGGUNA * 2}")
println("URL endpoint = http://${Konfigurasi.HOST}:${Konfigurasi.PORT}/api")
}
class Lingkaran(val radius: Double) {
fun luas(): Double = PI * radius * radius
fun keliling(): Double = 2 * PI * radius
}Output yang Dihasilkan:
=== Konstanta top-level (const val) ===
PI = 3.141592653589793
NAMA_APLIKASI= BelajarKotlin
VERSI = 1
MAX_PENGGUNA = 100
=== Konstanta di object (const val) ===
HOST = localhost
PORT = 8080
TIMEOUT_MS = 5000
=== Property val biasa (runtime) ===
waktuMulai (val) = 1700000000000000000
waktuAksesPertama (val) = 1700000000000001234
Selisih = 1234 ns
Lingkaran radius = 5.0
Luas lingkaran = 78.53981633974483
Keliling = 31.41592653589793
=== Demonstriasi inline const ===
Maks pengguna x 2 = 200
URL endpoint = http://localhost:8080/apiMari kita amati baris-baris penting pada kode di atas:
- Baris 1-4 —
const valdi top-level. Nilai-nilai ini disematkan ke bytecode sebagai konstanta — tidak ada inisialisasi runtime. - Baris 6-10 (
object Konfigurasi) —const valdi dalamobjectsingleton. Akses:Konfigurasi.HOST,Konfigurasi.PORT. Sama efisiennya dengan top-level. - Baris 12 (
val waktuMulai: Long = ...) —valbiasa (tanpaconst) di top-level. Nilai tetap disimpan sebagai propertystaticJVM, tetapi inisialisasi terjadi saat class dimuat — tidak seefisienconst val. - Baris 14 (
fun main()) — penggunaanPI,NAMA_APLIKASI, dll. langsung. Karenaconst, kompilator menyisipkan nilai literal ke bytecode. - Baris 31-33 (
lingkaran.luas(),lingkaran.keliling()) — classLingkaranmemakaiPIdari top-level konstanta. Perhitungan menjadi konstan jika inputradiusjuga konstan. - Baris 38 (
MAX_PENGGUNA * 2) — ekspresi yang melibatkan konstanta compile-time. Kompilator dapat mengevaluasiMAX_PENGGUNA * 2saat kompilasi menjadi200, menyematkan hasilnya sebagai konstanta baru di bytecode. - Baris 39 (
http://${Konfigurasi.HOST}:${Konfigurasi.PORT}/api) — string template dengan konstanta. Karena nilai sudah disematkan saat kompilasi, runtime hanya perlu merangkai string — efisien.
const val vs val biasa #
Perbedaan utama dirangkum pada tabel berikut:
| Aspek | const val | val biasa |
|---|---|---|
| Waktu evaluasi | Compile-time | Runtime (saat class/instance dimuat) |
| Tipe yang diizinkan | String atau primitive saja | Semua tipe |
| Lokasi | Top-level, object, companion object | Mana saja |
| Overhead inisialisasi | Tidak ada (inline ke bytecode) | Ada (akses field statis) |
Bisa untuk var | Tidak | Tidak relevan |
| Bisa untuk nilai hasil function | Tidak | Ya |
Kapan memilih const val #
| Skenario | Pilihan |
|---|---|
Konstanta matematika (PI, E) | const val |
Batas aplikasi (MAX_PENGGUNA, TIMEOUT_DETIK) | const val |
| Versi aplikasi, nama aplikasi | const val |
| Nilai yang bergantung pada config runtime | val biasa |
Nilai hasil function call (System.currentTimeMillis()) | val biasa |
Koleksi (listOf(...)) | val biasa |
Referensi Lanjutan #
- Properties
— dokumentasi properti Kotlin yang merincikan perbedaan
const val(compile-time) danval(runtime) - Coding conventions
— panduan konvensi penamaan Kotlin untuk
const valdan konstanta tingkat atas
Penggunaan const val yang tepat membuat program lebih efisien dan kode lebih jelas. Berikutnya, kita akan melihat bagaimana variabel hidup dan mati dalam scope blok — pada chapter Scope dan Lifetime.