Null Safety Dasar
Memahami null safety: kenapa null berbahaya dan cara Dart mengatasinya.
Mengakhiri mimpi buruk null
NullPointerException adalah error paling terkenal di dunia pemrograman, julukannya "kesalahan satu miliar dolar" karena miliaran jam debugging terbuang karenanya. Penyebabnya sederhana: kode memakai data yang ternyata kosong (null) tanpa mengecek dulu.
Null safety adalah jawaban Dart: sistem yang memaksa kamu menangani kemungkinan null sejak kode ditulis, bukan saat aplikasi crash di tangan pengguna.
Analogi: null safety itu seperti sabuk pengaman yang tidak bisa dilepas saat mobil jalan. Merepotkan di awal, tapi menyelamatkan nyawa (aplikasimu) nanti.
Kenapa null safety ada?
Sebelum null safety, variabel apa pun bisa null kapan saja, dan compiler diam saja. Error baru muncul saat runtime, di kondisi yang sulit direproduksi. Null safety membalik ini: compiler menjadi penjaga ketat yang menolak kode berisiko sejak awal.
Non-nullable vs nullable
Aturan intinya sederhana:
void main() {
String nama = 'Budi';
// nama = null; // ERROR: String tidak boleh null
String? panggilan; // ? artinya BOLEH null
print(panggilan); // null, nilai default variabel nullable
panggilan = 'Bang Budi';
print(panggilan); // Bang Budi
}String: non-nullable, dijamin tidak pernah null. Compiler menjaganya.String?: nullable, boleh null. Kamu wajib menanganinya sebelum dipakai.
Contoh kedua, null safety menangkap bug sejak compile:
void main() {
String? nama;
// print(nama.length); // ERROR COMPILE: nama bisa null!
// Compiler berkata: "tanganimu dulu kemungkinan null-nya"
// Cara 1: cek dulu
if (nama != null) {
print(nama.length); // OK: di sini compiler TAHU nama tidak null
}
// Cara 2: beri default
print(nama?.length ?? 0); // 0, aman
}Perhatikan keajaiban di Cara 1: setelah if (nama != null), compiler mempromosikan nama menjadi non-nullable di dalam blok. Ini disebut flow analysis, dan ia bekerja otomatis.
Kapan memakai nullable?
class Pengguna {
String nama; // wajib ada: non-nullable
String? bio; // opsional: nullable, boleh kosong
Pengguna(this.nama, [this.bio]);
}
void main() {
var u1 = Pengguna('Budi');
var u2 = Pengguna('Ani', 'Ngoding tiap hari');
print('${u1.nama}: ${u1.bio ?? "belum ada bio"}');
print('${u2.nama}: ${u2.bio}');
}Aturan jempol: default-nya non-nullable. Tambahkan ? hanya untuk data yang memang boleh kosong secara konsep (bio opsional, hasil pencarian yang mungkin tidak ketemu).
Kesalahan umum
1. Menabur ? di mana-mana agar "aman"
// SALAH: semua nullable = kamu bohong ke compiler
void main() {
String? nama = 'Budi';
int? umur = 17;
// ...lalu pusing menangani null di mana-mana
}// BENAR: ? hanya untuk yang memang boleh kosong
void main() {
String nama = 'Budi';
int umur = 17;
String? bio; // hanya ini yang opsional
}Terlalu banyak ? justru menambah beban: setiap pemakaian butuh penanganan null.
2. Memakai ! untuk membungkam compiler
// BERBAHAYA
void main() {
String? nama;
// print(nama!.length); // compile OK, tapi CRASH saat runtime!
}// BENAR
void main() {
String? nama = 'Budi';
if (nama != null) {
print(nama.length); // aman, tanpa !
}
}Operator ! (null assertion) artinya "aku jamin tidak null". Kalau jaminanmu salah, aplikasi crash. Pakai hanya saat kamu benar-benar yakin, mis. setelah validasi yang tidak bisa dibaca compiler.
3. Lupa inisialisasi field non-nullable
// SALAH
// class Siswa {
// String nama; // ERROR: non-nullable harus diisi
// }// BENAR: tiga jalan keluar
class Siswa {
String nama = ''; // 1. nilai default
}
class Siswa2 {
String nama; // 2. via constructor
Siswa2(this.nama);
}
class Siswa3 {
late String nama; // 3. late: janji diisi sebelum dipakai
void isi(String n) => nama = n;
}Kata kunci late dibahas detail di modulnya sendiri.
Kesimpulan
Null safety = compiler sebagai penjaga null. Default non-nullable, ? hanya untuk yang memang boleh kosong, tangani dengan if != null atau ??, hindari ! kecuali yakin. Fitur ini adalah alasan utama Dart modern minim crash null.
Catatan teknis: Null safety Dart bersifat sound: jika kode lolos compile tanpa
!, dijamin tidak ada null dereference saat runtime. Jaminan sekuat ini langka di bahasa mainstream.
Tantangan
Sambutan aman null
Buat fungsi sapa(String? nama) yang mencetak "Halo, {nama}!" jika nama tidak null, atau "Halo, tamu!" jika null. Jangan pakai !.
// TODO: fungsi sapa
void main() {
// TODO: panggil dengan 'Rina' dan dengan null
}