Belajar Kotlin - Null Safety & Type System
Episode 6 of 23

Belajar Kotlin - Null Safety & Type System

Episode ini membedah null safety dan sistem tipe Kotlin: nullable types dan safe call operator, elvis operator dan non-null assertions, smart casts dan type inference, hingga inline classes dan value classes yang menjaga kode tetap aman dan performa tetap optimal.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Null safety adalah alasan utama banyak tim meninggalkan Java dan pindah ke Kotlin. Episode 6 membedah sistem tipe yang membuat sebagian besar NullPointerException gagal di tahap kompilasi, bukan di production. Kalian akan belajar nullable types, safe call operator, elvis operator, dan smart casts.

Selain null safety, episode ini juga menyinggung tipe inferensi dan inline classes — fitur yang memungkinkan membuat tipe baru tanpa overhead alokasi objek.

Setelah episode ini, kalian akan memahami mengapa Kotlin disebut bahasa yang "null-safe" dan bagaimana memanfaatkannya untuk menulis kode yang jauh lebih sedikit bugnya.

Nullable Types dan Safe Call

Menandai Tipe yang Bisa Null

Di Kotlin, tipe String tidak pernah bisa menyimpan null. Jika sebuah variabel berpotensi null, tipe harus ditulis String?. Compiler menegakkan penanganan null di titik pemakaian:

KotlinTipe nullable
val nama: String? = null
val panjang = nama.length

Baris kedua di atas tidak akan lolos kompilasi — compiler tahu nama bisa null dan menolak akses langsung. Inilah yang dimaksud null safety: masalah terdeteksi saat build, bukan saat aplikasi crash di tangan pengguna.

Safe Call Operator

Untuk mengakses member dari nilai nullable dengan aman, gunakan operator ?.. Jika receiver-nya null, seluruh ekspresi mengembalikan null tanpa melempar exception:

KotlinSafe call operator
val nama: String? = null
val panjang = nama?.length
println(panjang) // null, bukan crash

nama?.length menghasilkan Int? — null jika nama null, panjang string jika tidak. Rantai safe call seperti pengguna?.alamat?.kota menghilangkan seluruh blok if-null bersarang yang biasa ditulis di Java.

Elvis Operator dan Non-null Assertion

Elvis: Nilai Default yang Ringkas

Elvis operator ?: mengembalikan nilai di sisi kanan jika ekspresi di sisi kiri bernilai null. Ini menggantikan blok if (x != null) x else default:

KotlinElvis operator
val nama: String? = null
val tampil = nama ?: "anonim"
println(tampil) // anonim

nama ?: "anonim" berarti: jika nama bukan null, pakai nilainya; jika null, pakai "anonim". Elvis sering dikombinasikan dengan return dan throw untuk menghentikan alur saat data tidak ada, seperti val h = tinggi ?: return 0.

Non-null Assertion: Pakai dengan Hati-hati

Operator !! memaksa nilai nullable menjadi non-null, dan melempar NullPointerException jika nilainya ternyata null. Ini disebut "pada tanggung jawab sendiri":

KotlinNon-null assertion
val nilai: String? = cariNilai()
val pastiAda = nilai!!

Pakai !! hanya ketika kalian yakin nilai tidak mungkin null — misalnya setelah validasi sebelumnya. Dalam kode produksi, !! sering dianggap bau kode: lebih baik gunakan safe call atau elvis agar perilaku null yang tidak terduga tertangkap dengan jelas.

Smart Casts dan Type Inference

Smart Cast dalam when dan if

Kotlin melakukan smart cast: jika compiler bisa membuktikan sebuah nilai tidak null (atau sudah tipe tertentu) dalam sebuah scope, dia otomatis meng-cast tanpa sintaks tambahan:

KotlinSmart cast
fun hitungPanjang(teks: String?): Int {
    if (teks == null) return 0
    return teks.length // teks sudah non-null di sini
}

Setelah pemeriksaan teks == null yang mengembalikan 0, compiler tahu teks pasti non-null — jadi teks.length dipanggil tanpa safe call. Smart cast juga bekerja untuk tipe: setelah is String, nilai diperlakukan sebagai String secara otomatis.

Type Inference Tetap Ketat

Type inference memungkinkan menulis tanpa tipe eksplisit, tapi compiler tetap memeriksa semua operasi. Tipe inferensi kadang menghasilkan tipe nullable tanpa disadari — misalnya dari fungsi yang mengembalikan String?. Biasakan memeriksa tipe yang diinferensikan dengan IDE untuk menghindari kejutan.

Inline Classes dan Value Classes

Membungkus Nilai Tanpa Overhead

Value class (sebelumnya inline class) memungkinkan membuat tipe pembungkus yang aman secara semantik tanpa alokasi objek saat runtime — nilai dibungkus langsung di tipe yang mendasarinya:

KotlinValue class
@JvmInline
value class Usia(val nilai: Int)
 
@JvmInline
value class Nama(val nilai: String)
 
fun sapa(nama: Nama, usia: Usia): String {
    return "Halo ${nama.nilai}, umur ${usia.nilai}"
}

Usia dan Nama adalah tipe berbeda di level kompilasi — kalian tidak akan salah kirim Usia ke parameter Nama — tapi saat runtime keduanya direpresentasikan sebagai Int dan String tanpa objek pembungkus. Fitur ini memberikan keamanan tipe tanpa biaya performa.

Kapan Memakai Value Class

Gunakan value class untuk membungkus primitif yang punya makna domain berbeda, seperti Usia, Harga, ID, atau Email. Keuntungannya ganda: kode lebih ekspresif dan bug pertukaran argumen terdeteksi saat kompilasi, tanpa penalti alokasi objek.

Praktik Null Safety yang Disarankan

Beberapa kebiasaan yang menjaga kode tetap aman:

  • Selalu deklarasikan tipe sebagai non-nullable kecuali memang bisa null.
  • Gunakan ?. untuk akses berantai yang mungkin null.
  • Gunakan ?: untuk nilai default alih-alih !!.
  • Batasi !! hanya pada titik yang benar-benar dijamin non-null.
  • Manfaatkan smart cast setelah pemeriksaan == null atau is Tipe.

Penutup

Episode 6 membekali kalian sistem pertahanan paling berharga di Kotlin: nullable types dengan safe call, elvis operator untuk nilai default, smart casts yang otomatis, serta value classes yang memadukan keamanan tipe dengan performa runtime.

Inti yang harus dibawa pulang:

  • Tipe non-nullable dan nullable dipisahkan secara eksplisit dengan tanda tanya.
  • ?. memanggil member dengan aman; ekspresi menghasilkan null saat receiver null.
  • ?: memberikan nilai default untuk kasus null.
  • !! memaksa non-null dan bisa melempar exception — gunakan hemat.
  • Smart cast membuktikan non-null atau tipe tertentu secara otomatis.
  • Value class memberi tipe domain tanpa overhead alokasi objek.

Di episode 7 selanjutnya kita akan membahas functional programming dan lambdas — lambda dan anonymous functions, function references, scope functions seperti let, run, apply, also, dan with, pola immutability, serta functional idioms yang membuat transformasi data menjadi ekspresif.