Sebuah aplikasi yang sudah berjalan mungkin mengalami eror dan crash. Kondisi eror pada saat aplikasi berjalan (runtime) ini dikenal dengan exception. Exceptions adalah kondisi yang tidak diharapkan yang terjadi selama eksekusi program, seperti kesalahan saat mencoba membaca file yang tidak ada atau membagi bilangan dengan nol.
Dalam bahasa Dart, exceptions adalah mekanisme untuk menangani kesalahan tersebut agar aplikasi tidak langsung berhenti bekerja. Kali ini kita akan membahas tentang jenis-jenis exceptions, cara melempar (throwing) exceptions, dan cara menangani (handling) exceptions dalam Dart.
Jenis-jenis Exceptions
Dalam Dart, exceptions digunakan untuk menangani kesalahan yang terjadi selama eksekusi program. Dart menyediakan berbagai jenis exceptions yang dapat digunakan untuk mengindikasikan berbagai jenis kesalahan. Berikut adalah beberapa exceptions yang umum digunakan dalam Dart:
1. Exception
Exception
adalah kelas dasar untuk semua exceptions yang tidak termasuk dalam jenis exceptions lainnya. Ini biasanya digunakan sebagai titik awal untuk membuat custom exceptions.
void main() {
throw Exception('This is a generic exception.');
}
Dalam contoh ini, sebuah Exception
generik dilempar dengan pesan 'This is a generic exception.'.
2. FormatException
FormatException
digunakan ketika ada kesalahan dalam format data. Ini sering terjadi ketika parsing string ke tipe data tertentu dan format string tersebut tidak sesuai dengan yang diharapkan.
void main() {
try {
int number = int.parse('abc');
} catch (e) {
print(e); // Output: FormatException: Invalid radix-10 number (at character 1)
}
}
Di sini, mencoba mengkonversi string 'abc' menjadi integer menyebabkan FormatException
karena 'abc' bukanlah format yang valid untuk integer.
3. IOException
IOException
digunakan untuk kesalahan yang terjadi selama operasi I/O (Input/Output). Ini sering digunakan dalam operasi file atau jaringan ketika terjadi masalah seperti file tidak ditemukan atau koneksi jaringan gagal.
import 'dart:io';
void main() {
try {
File file = File('non_existent_file.txt');
String content = file.readAsStringSync();
} catch (e) {
print(e); // Output: FileSystemException: Cannot open file, path = 'non_existent_file.txt' (OS Error: No such file or directory)
}
}
Dalam contoh ini, mencoba membaca file yang tidak ada akan menyebabkan IOException
.
4. TimeoutException
TimeoutException
digunakan ketika operasi memakan waktu lebih lama dari yang diharapkan. Ini sering digunakan dalam operasi jaringan atau asynchronous yang memiliki batas waktu tertentu untuk menyelesaikan.
import 'dart:async';
void main() {
Future.delayed(Duration(seconds: 3), () => 'Hello, World!')
.timeout(Duration(seconds: 1))
.catchError((e) {
print(e); // Output: TimeoutException after 0:00:01.000000: Future not completed
});
}
Di sini, operasi asynchronous yang seharusnya selesai dalam 3 detik akan menyebabkan TimeoutException
karena batas waktu yang ditentukan hanya 1 detik.
5. StateError
StateError
digunakan ketika ada kesalahan pada keadaan objek, misalnya jika kita mencoba mengakses elemen pada koleksi yang kosong atau mengubah keadaan objek yang tidak valid.
void main() {
List<int> numbers = [];
try {
print(numbers.first);
} catch (e) {
print(e); // Output: StateError: No element
}
}
Dalam contoh ini, mencoba mengakses elemen pertama dari daftar yang kosong akan menyebabkan StateError
.
Handling Exceptions
Dart menyediakan dua cara utama untuk menangani exceptions: menggunakan blok try-catch
dan menggunakan blok try-catch-finally
. Penanganan exceptions ini penting untuk memastikan bahwa aplikasi tetap berjalan meskipun terjadi kesalahan.
1. Try-Catch
Blok try-catch
digunakan untuk menangkap exceptions yang dilempar di dalam blok try
. Blok ini memungkinkan Anda untuk menjalankan kode yang mungkin melempar exceptions dan menangkap serta menangani exceptions tersebut di blok catch
.
void main() {
try {
int result = 12 ~/ 0; // Operasi pembagian bilangan bulat dengan nol
} catch (e) {
print('Error: $e'); // Output: Error: IntegerDivisionByZeroException
}
}
Dalam contoh di atas, blok try
berisi kode yang mungkin melempar exception, yaitu operasi pembagian bilangan bulat dengan nol. Sedangkan blok catch
menangkap IntegerDivisionByZeroException
yang dilempar dan mencetak pesan error.
2. Try-Catch-Finally
Blok try-catch-finally
digunakan untuk menangkap exceptions dan juga menjalankan kode tertentu setelah blok try
atau catch
dieksekusi, terlepas dari apakah exception dilempar atau tidak. Blok finally
sering digunakan untuk membersihkan resource, seperti menutup file atau mengakhiri koneksi jaringan.
void main() {
try {
int result = 12 ~/ 0; // Operasi pembagian bilangan bulat dengan nol
} catch (e) {
print('Error: $e'); // Output: Error: IntegerDivisionByZeroException
} finally {
print('This is always executed.'); // Output: This is always executed.
}
}
Dalam contoh ini, blok try
berisi kode yang mungkin melempar exception. Kemudian, blok catch
menangkap dan menangani exception yang dilempar. Sedangkan blok finally
berisi kode yang akan selalu dijalankan, baik exception dilempar atau tidak. Ini sering digunakan untuk tugas pembersihan seperti menutup file atau membebaskan resource lainnya.
3. Menangkap Berbagai Jenis Exceptions
Kadang-kadang, Anda mungkin ingin menangkap dan menangani berbagai jenis exceptions secara berbeda. Anda dapat melakukan ini dengan menggunakan beberapa blok catch
.
void main() {
try {
int result = 12 ~/ 0; // Operasi pembagian bilangan bulat dengan nol
} on IntegerDivisionByZeroException catch (e) {
print('Cannot divide by zero: $e'); // Output: Cannot divide by zero: IntegerDivisionByZeroException
} catch (e) {
print('An error occurred: $e');
}
}
Dalam contoh ini, blok on IntegerDivisionByZeroException catch (e)
digunakan untuk menangkap IntegerDivisionByZeroException
secara khusus. Sedangkan blok catch (e)
umum digunakan untuk menangkap exceptions lainnya.
4. Custom Exceptions
Kita juga dapat membuat custom exceptions dan menangkapnya dengan cara yang sama seperti exceptions bawaan.
class AgeException implements Exception {
String cause;
AgeException(this.cause);
}
void checkAge(int age) {
if (age < 18) {
throw AgeException('Age must be at least 18.');
}
}
void main() {
try {
checkAge(15);
} on AgeException catch (e) {
print('AgeException: ${e.cause}'); // Output: AgeException: Age must be at least 18.
} catch (e) {
print('An error occurred: $e');
}
}
Dalam contoh ini, AgeException
adalah custom exception yang didefinisikan untuk menangani kesalahan usia. Kemudian, blok try
berisi kode yang mungkin melempar AgeException
. Sehingga blok on AgeException catch (e)
digunakan untuk menangkap dan menangani AgeException
.
Exceptions adalah alat penting dalam pemrograman untuk menangani kesalahan yang tidak terduga dan memastikan bahwa aplikasi kita tetap berjalan dengan baik. Dart menyediakan berbagai mekanisme untuk melempar dan menangani exceptions, termasuk try-catch
, try-catch-finally
, dan custom exceptions. Dengan memahami dan menggunakan exceptions dengan benar, kita dapat membuat aplikasi Dart yang lebih robust dan error-tolerant.