Semua pengecualian di Dart adalah pengecualian tidak terperiksa. Kita tidak perlu mendeklarasikan tipe yang dilemparkan di dalam fungsi, dan menangkapnya tidak wajib dilakukan.
Terdapat dua kategori utama:
Exception:Kesalahan yang dapat diprediksi dari logika bisnis (masalah format data, parameter tidak valid, dll. Disarankan untuk ditangkap dan diolah).Error:Kesalahan fatal program (ketidakcocokan tipe data, penunjuk nol, metode yang belum diimplementasikan, dll. Umumnya tidak ditangkap).
Semua objek yang tidak bernilai null dapat dilemparkan menggunakan kata kunci throw. Di proyek yang terstruktur rapi, hanya subkelas dari Exception/Error yang dilemparkan.
Pengecualian yang tidak tertangkap akan menghentikan isolate saat ini dan menyebabkan aplikasi crash.
throw: Melempar pengecualian
1. Melempar pengecualian bawaan sistem
void main() {
// Pengecualian format data
throw FormatException("Minimal satu segmen data diperlukan");
}
Code language: JavaScript (javascript)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
FormatException: Deskripsi kesalahan
#0 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:3)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
Kode ini melempar pengecualian bawaan dengan pesan buatan sendiri yang akan muncul saat program dijalankan. Mungkin Anda bertanya apa kegunaannya, namun mekanisme pelemparan pengecualian sangat penting dalam pengembangan. Sebagai contoh, saat pendaftaran pengguna kita validasi data masukan: jika tidak memenuhi aturan, kita langsung lempar pengecualian untuk menghentikan alur dan memberi peringatan kepada pengguna, sehingga data yang salah tidak masuk ke sistem dan integritas data tetap terjaga.
2. Melempar objek apa pun
Tidak disarankan untuk lingkungan produksi
void main() {
throw "Teks deskripsi kesalahan!";
}Code language: JavaScript (javascript)
Hasil eksekusi
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
Teks deskripsi kesalahan!
#0 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:2:3)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
3. Menggunakan throw di fungsi panah (throw merupakan ekspresi)
class Point {}
void distanceTo(Point other) => throw UnimplementedError("Metode ini belum diimplementasikan");
void main() {
distanceTo(Point());
}
Code language: JavaScript (javascript)
III. Menangkap pengecualian dengan try /on/catch
Perbedaan sintaks
on TipePengecualian:Hanya cocok dengan pengecualian tipe yang ditentukan, objek pengecualian tidak dapat diakses.catch(e):Menangkap semua jenis pengecualian, variabel e menyimpan instans pengecualian.catch(e, s):e = objek pengecualian, s = informasi tumpukan panggilan StackTrace.
1: Menangkap satu tipe pengecualian dengan on
// Membuat kelas pengecualian kustom yang mengimplementasikan Exception
class OutOfLlamasException implements Exception {}
// Fungsi yang melempar pengecualian kustom di atas
void breedMoreLlamas() {
throw OutOfLlamasException();
}
void buyMoreLlamas() {
print("Fungsi buyMoreLlamas telah dieksekusi");
}
void main() {
try {
breedMoreLlamas(); // Panggil fungsi yang berisi kode berisiko
} on OutOfLlamasException {
buyMoreLlamas(); // Akan dijalankan jika OutOfLlamasException tertangkap
}
}Code language: JavaScript (javascript)
Hasil eksekusi
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Fungsi buyMoreLlamas telah dieksekusiCode language: CSS (css)
try {
// Kode yang berpotensi menimbulkan kesalahan
} on KelasPengecualian {
// Logika yang dijalankan jika kesalahan tertangkap
}Code language: JavaScript (javascript)
try on hanyalah sintaks khusus untuk menangkap pengecualian berdasarkan tipe.
2: Penangkapan hierarkis dengan banyak cabang
Cocokan yang lebih akurat akan diproses terlebih dahulu
class OutOfLlamasException implements Exception {}
void breedMoreLlamas() {
throw FormatException("Kesalahan format data");
}
void main() {
try {
breedMoreLlamas();
}
// 1. Cocokan tepat dengan pengecualian kustom
on OutOfLlamasException {
print("Terjadi kesalahan OutOfLlamasException");
}
// 2. Tangkap semua subkelas dari Exception
on Exception catch (e) {
print("Pengecualian bisnis umum: $e");
}
// 3. Cabang cadangan untuk Error dan objek lain yang dilemparkan
catch (e) {
print("Kesalahan serius tidak diketahui: $e");
}
}
Code language: PHP (php)
Hasil keluaran: Pengecualian bisnis umum: FormatException: Kesalahan format data
Kita dapat menggunakan beberapa blok on untuk menangkap tiap jenis Exception secara terpisah, lalu melengkapinya dengan catch sebagai cadangan universal.
3: Tangkap pengecualian + cetak tumpukan panggilan StackTrace
void main() {
try {
int a = null;
print(a + 1);
} catch (e, stack) {
print("Informasi pengecualian: $e");
print("Tumpukan panggilan lengkap:\n$stack");
}
}
Code language: PHP (php)
Kode ini tidak hanya menampilkan pesan kesalahan, melainkan juga seluruh rantai panggilan fungsi untuk proses debug.
D:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:3:13: Error: A value of type 'Null' can't be assigned to a variable of type 'int'.
int a = null;Code language: PHP (php)
IV. rethrow
Olah sebagian lalu lempar kembali ke atas
Fungsi: fungsi saat ini menjalankan sebagian logika pemulihan, kemudian kirim pengecualian ke pemanggil untuk diproses tambahan.
Terkadang kesalahan tidak dapat sepenuhnya diolah di fungsi saat ini, kita perlu melempar kembali pengecualian agar kode pemanggil juga dapat menangani.
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Tipe true tidak mendukung inkremen, timbul kesalahan saat runtime
} catch (e) {
print("Pengolahan lokal di misbehave: ${e.runtimeType}");
rethrow; // Lempar kembali agar tertangkap try luar
}
}
void main() {
try {
misbehave();
} catch (e) {
print("Pengolahan akhir di main: ${e.runtimeType}");
}
}
Code language: PHP (php)
Alur eksekusi:
Pengolahan lokal di misbehave: NoSuchMethodError
Pengolahan akhir di main: NoSuchMethodError
Kode di atas mengolah kesalahan baik di fungsi misbehave maupun di main.
V. Blok finally
Akan selalu dieksekusi, ada kesalahan atau tidak
Dua skenario penggunaan:
- Hanya try + finally: pengecualian tidak tertangkap, aplikasi crash setelah finally dijalankan
- try + catch + finally: olah kesalahan terlebih dahulu lalu jalankan finally (khusus untuk melepaskan sumber daya)
1: try + finally
void cleanLlamaStalls() => print("Bersihkan sumber daya, blok cadangan yang pasti jalan");
void breedMoreLlamas() => throw Exception("Terjadi kesalahan");
void main() {
try {
breedMoreLlamas();
} finally {
cleanLlamaStalls();
}
}
Code language: PHP (php)
Kode pembersihan akan berjalan, namun pengecualian yang tidak tertangkap akan membuat program crash di akhir.
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Bersihkan sumber daya, blok cadangan yang pasti jalan
Unhandled exception:
Exception: Terjadi kesalahan
#0 breedMoreLlamas (file:///D:/dartdemo/firstdart/bin/firstdart.dart:2:27)
#1 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:5)
#2 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#3 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
2: try + catch + finally
Sintaks standar untuk melepaskan sumber daya, contohnya menutup file yang dibuka
void cleanLlamaStalls() => print("Tutup file / lepaskan sumber daya sistem");
void breedMoreLlamas() => throw FormatException("Gagal parsing");
void main() {
try {
breedMoreLlamas();
} catch (e) {
print("Pengecualian tertangkap: $e");
} finally {
cleanLlamaStalls();
}
}
Code language: PHP (php)
Urutan eksekusi: pengecualian muncul → olah di catch → jalankan finally
Hasil eksekusi
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Pengecualian tertangkap: FormatException: Gagal parsing
Tutup file / lepaskan sumber daya sistem
VI. assert: pernyataan asersi
Hanya aktif saat pengembangan dan debug, akan nonaktif sepenuhnya di produksi
assert(kondisiBoolean, [pesanKesalahanOpsional])
Jika kondisi bernilai false, akan dilemparkan AssertionError. Di build produksi seluruh kode assert diabaikan tanpa beban performa.
1: Contoh asersi dasar
void main() {
String? text;
int number = 120;
String url = "http://foxdevelop.com";
assert(text != null); // Cek apakah tidak null
assert(number < 100); // Validasi rentang angka
assert(url.startsWith("https")); // Cek protokol tautan
}
Code language: JavaScript (javascript)
Jika jalankan kode ini apa pun tidak akan keluar secara default!
Asersi secara default nonaktif, harus diaktifkan lewat parameter jalankan, lihat di bawah.
2: Pesan kesalahan kustom untuk asersi
void main() {
String url = "http://test.com";
assert(
url.startsWith("https"),
"Tautan $url harus diawali dengan https",
);
}
Code language: JavaScript (javascript)
Kita bisa menentukan sendiri pesan yang muncul saat asersi gagal.
Cara mengaktifkan assert
- Mode Debug Flutter: asersi aktif secara default
- Jalankan via perintah dart:
dart --enable-asserts nama-file.dart - Build produksi: semua kode assert dihapus, tidak ada penurunan performa
D:\dartdemo\firstdart\bin>dart --enable-asserts firstdart.dart
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
Perintah dart run dan dart biasa secara default menonaktifkan assert, harus tambahkan flag --enable-asserts:
Contoh perintah jalankan
dart run --enable-asserts main.dartCode language: CSS (css)
Jika terminal sudah berada di folder root proyek, bisa gunakan versi singkat:
Perintah jalankan:
dart run --enable-asserts
dart run:Jalankan kode sumber Dart langsung untuk pengembangan dan debug
dart nama-file:Sintaks ringkas untuk satu file
dart compile exe:Kompilasi menjadi biner mandiri, assert selalu nonaktif di hasil kompilasi
File Dart ada di folder bin proyek. Kita bisa masuk ke bin jalankan file langsung atau naik satu tingkat ke root proyek jalankan seluruh proyek.
dart run –enable-asserts
Berikut dua cara: jalankan dari folder bin dan jalankan dari root proyek induk.
D:\dartdemo\firstdart\bin>dart --enable-asserts firstdart.dart
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)
D:\dartdemo\firstdart\bin>dart run
Building package executable...
Built firstdart:firstdart.
D:\dartdemo\firstdart\bin>cd ..
D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
Jika kondisi asersi bernilai true, tidak akan ada pengecualian yang dilemparkan.
Ubah contoh kode: ganti http menjadi https di URL, ubah text != null menjadi text == null dan isi variabel number dengan 99
void main() {
String? text;
int number = 99;
String url = "https://foxdevelop.com";
assert(text == null); // Cek nilai null
assert(number < 100); // Validasi rentang angka
assert(url.startsWith("https")); // Cek protokol URL
}Code language: JavaScript (javascript)
Saat dijalankan kembali, tidak akan muncul kesalahan sama sekali.
D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.Code language: CSS (css)
VII. Contoh Lengkap
void cleanResource() => print("finally: lepaskan sumber daya yang terpakai");
void testError() {
try {
int num = 150;
assert(num < 100, "Angka harus kurang dari 100");
throw FormatException("Format data tidak valid");
} on FormatException catch (e) {
print("Pengecualian format tertangkap: $e");
rethrow;
} finally {
cleanResource();
}
}
void main() {
try {
testError();
} catch (e) {
print("main menangkap pengecualian yang dilemparkan kembali: $e");
}
}
Code language: PHP (php)
Hasil eksekusi
D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.
finally: lepaskan sumber daya yang terpakai
main menangkap pengecualian yang dilemparkan kembali: 'file:///D:/dartdemo/firstdart/bin/firstdart.dart':
Failed assertion: line 6 pos 12: 'num < 100': Angka harus kurang dari 100Code language: PHP (php)
Contoh lengkap seluruh alur penanganan pengecualian dan kesalahan