Penanganan Pengecualian dan Kesalahan

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:

  1. Hanya try + finally: pengecualian tidak tertangkap, aplikasi crash setelah finally dijalankan
  2. 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

  1. Mode Debug Flutter: asersi aktif secara default
  2. Jalankan via perintah dart: dart --enable-asserts nama-file.dart
  3. 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

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *