Bahasa seperti Java membedakan tipe primitif (int, double, boolean) dari tipe reference (Integer, Double, Boolean). Kotlin tidak menampilkan perbedaan ini di kode — semua tipe diperlakukan sebagai objek. Namun, kompilator Kotlin tetap memanfaatkan primitive types JVM untuk efisiensi memori dan kecepatan pada situasi tertentu. Pada chapter ini kita akan membedah kapan kompilator memakai primitive, kapan memakai boxed reference, serta dampak nullabilitas terhadap representasi internal.
Kotlin tidak punya primitive types di kode #
Di Kotlin, kita tidak menulis int atau Integer — kita cukup menulis Int. Kompilator memilih representasi JVM yang paling efisien di balik layar. Saat Int digunakan dalam konteks non-nullable, kompilator biasanya menerjemahkannya ke primitive int JVM; saat digunakan sebagai nullable Int?, kompilator memakai boxed java.lang.Integer.
val a: Int = 42 // JVM: int (primitive)
val b: Int? = 42 // JVM: java.lang.Integer (boxed)
val c: Long = 42L // JVM: long (primitive)
val d: Double = 42.0 // JVM: double (primitive)
val e: String = "halo" // JVM: java.lang.String (reference)Demonstrasi representasi JVM #
Berikut program yang memperlihatkan perbedaan kelas runtime antara tipe non-nullable dan nullable:
fun main() {
val a: Int = 42
val b: Int? = 42
val c: Long = 42L
val d: Double = 42.0
val e: String = "halo"
println("a (Int) = $a -> ${a.javaClass.name}")
println("b (Int?) = $b -> ${b?.javaClass?.name}")
println("c (Long) = $c -> ${c.javaClass.name}")
println("d (Double) = $d -> ${d.javaClass.name}")
println("e (String) = $e -> ${e.javaClass.name}")
val daftarNonNull: List<Int> = listOf(1, 2, 3)
val daftarNullable: List<Int?> = listOf(1, null, 3)
println("List<Int> -> ${daftarNonNull.javaClass.name}")
println("List<Int?> -> ${daftarNullable.javaClass.name}")
val jumlahNonNull = daftarNonNull.sum()
val jumlahNullable = daftarNullable.filterNotNull().sum()
println("Jumlah non-null : $jumlahNonNull")
println("Jumlah nullable: $jumlahNullable")
}Output yang Dihasilkan:
a (Int) = 42 -> int
b (Int?) = 42 -> java.lang.Integer
c (Long) = 42 -> long
d (Double) = 42.0 -> double
e (String) = halo -> java.lang.String
List<Int> -> java.util.Arrays$ArrayList
List<Int?> -> java.util.Arrays$ArrayList
Jumlah non-null : 6
Jumlah nullable: 4Mari kita amati baris-baris penting pada kode di atas:
- Baris 2 (
val a: Int = 42) —a.javaClass.namemenghasilkanint(huruf kecil) karena kompilator memakai primitive JVM. - Baris 3 (
val b: Int? = 42) — karenabnullable, kompilator memakaijava.lang.Integer(boxed). Property.javaClassdipanggil dengan?.karena receiver nullable. - Baris 4-5 (
val c: Long = 42L,val d: Double = 42.0) —LongdanDoublenon-nullable dipetakan ke primitivelongdandouble. - Baris 6 (
val e: String = "halo") —Stringadalah tipe reference di JVM, tidak ada bentuk primitifnya. - Baris 8-9 (
List<Int>vsList<Int?>) — elemenList<Int>disimpan sebagai primitiveint[]di balik layar; elemenList<Int?>harus disimpan sebagaiInteger[]karena bisanull. - Baris 11-12 (
daftarNonNull.sum()vsdaftarNullable.filterNotNull().sum()) —List<Int?>memerlukan.filterNotNull()sebelum operasi numerik karena elemen nullable tidak bisa langsung dijumlahkan.
Kapan primitive dipakai #
Kompilator Kotlin memakai primitive JVM ketika semua kondisi berikut terpenuhi:
- Tipe non-nullable (
Int, bukanInt?). - Tipe bukan tipe generik (bukan parameter type
T). - Variabel lokal, field pada class, atau parameter function.
Jika salah satu kondisi tidak terpenuhi (misalnya variabel nullable, atau disimpan dalam List<Int?>), kompilator memakai boxed reference.
val a: Int = 42 // primitive int
val b: Int? = 42 // boxed Integer
val c: List<Int> = listOf(1, 2, 3) // primitive-backed list (tergantung implementasi)
val d: List<Int?> = listOf(1, null, 3) // boxed Integer listDampak performa dan memory #
| Konteks | Representasi JVM | Memori per elemen | Catatan |
|---|---|---|---|
Int non-nullable lokal | int primitive | 4 byte | tercepat, paling hemat |
Int? nullable | Integer boxed | 16+ byte | ada overhead header objek |
Array<Int> | Integer[] | 16+ byte per elemen | selalu boxed |
IntArray | int[] | 4 byte per elemen | primitive array khusus |
Referensi Lanjutan #
- Basic types — pengantar tipe dasar Kotlin yang menjelaskan representasi primitive vs reference di JVM
- Numbers — dokumentasi tipe angka Kotlin termasuk boxing otomatis untuk tipe reference
Pemahaman tentang bagaimana Kotlin memetakan tipe ke JVM membantu kita menulis kode yang efisien. Berikutnya, kita akan menjelajahi seluruh keluarga tipe angka — Byte, Short, Int, Long, Float, Double — pada chapter Numbers.