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.

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.
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:
val nama: String? = null
val panjang = nama.lengthBaris 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.
Untuk mengakses member dari nilai nullable dengan aman, gunakan operator ?.. Jika receiver-nya null, seluruh ekspresi mengembalikan null tanpa melempar exception:
val nama: String? = null
val panjang = nama?.length
println(panjang) // null, bukan crashnama?.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 ?: mengembalikan nilai di sisi kanan jika ekspresi di sisi kiri bernilai null. Ini menggantikan blok if (x != null) x else default:
val nama: String? = null
val tampil = nama ?: "anonim"
println(tampil) // anonimnama ?: "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.
Operator !! memaksa nilai nullable menjadi non-null, dan melempar NullPointerException jika nilainya ternyata null. Ini disebut "pada tanggung jawab sendiri":
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.
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:
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 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.
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:
@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.
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.
Beberapa kebiasaan yang menjaga kode tetap aman:
?. untuk akses berantai yang mungkin null.?: untuk nilai default alih-alih !!.!! hanya pada titik yang benar-benar dijamin non-null.== null atau is Tipe.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:
?. 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.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.