Try-Catch: esensi, konstruksi penangkapan eksepsi dan cara kerjanya dalam pengembangan mobile

Penulis: IT Sectr Diterbitkan: 2026-05-25 Waktu membaca: 9 mnt

Try-Catch — konstruksi penangkapan eksepsi yang memungkinkan eksekusi kode yang berpotensi berbahaya dalam blok yang dilindungi dan menangani kesalahan dengan benar tanpa penghentian program secara tiba-tiba. Blok try berisi kode yang dapat melempar eksepsi, catch menangkapnya dan menjalankan logika pemulihan. Menurut Apple Swift Documentation (2026), blok finally dieksekusi terlepas dari apakah eksepsi dilemparkan atau tidak, menjamin pembebasan sumber daya.

Poin Utama

  • Try-Catch — konstruksi untuk menangkap eksepsi yang mencegah penghentian program secara tiba-tiba saat terjadi kesalahan
  • Blok try berisi kode yang dapat melempar eksepsi — eksekusi dihentikan pada kesalahan pertama
  • Blok catch menangkap eksepsi dari tipe yang ditentukan dan menjalankan logika penanganan atau pemulihan
  • Blok finally dieksekusi secara terjamin setelah try/catch untuk membebaskan sumber daya, misalnya menutup file
  • Try-catch bersarang memungkinkan penanganan kesalahan di berbagai tingkat abstraksi dalam satu fungsi

Apa itu Try-Catch?

Try-Catch — konstruksi fundamental penanganan eksepsi terstruktur yang ada di sebagian besar bahasa pemrograman modern. Terdiri dari tiga blok: try (percobaan mengeksekusi kode berbahaya), catch (menangkap dan menangani eksepsi) dan finally opsional (finalisasi). Ide konstruksinya adalah memisahkan logika operasi bisnis dari logika penanganan kesalahan, membuat kode lebih mudah dibaca dan diprediksi.

Konsep ini pertama kali diimplementasikan dalam bahasa C++ sebagai try/catch, kemudian diadopsi oleh Java, C#, Swift, Kotlin, Dart, Python, JavaScript dan bahasa lainnya. Setiap bahasa menambahkan fiturnya sendiri: di Swift blok catch harus lengkap, di Kotlin try-catch bisa menjadi ekspresi (expression), di Dart finally wajib untuk sumber daya aliran. Terlepas dari perbedaannya, prinsip dasarnya sama: kesalahan ditangani sedekat mungkin dengan tempat terjadinya, bukan secara global.

Penggunaan Try-Catch sangat relevan dalam pengembangan mobile, di mana faktor eksternal — kehilangan jaringan, respons server yang salah, kekurangan memori — terus terjadi. Penanganan eksepsi yang benar mencegah crash aplikasi dan memastikan UX yang tepat: pengguna menerima pesan kesalahan alih-alih penutupan aplikasi secara tiba-tiba. Menurut Google Android Kotlin Style Guide (2026), setiap fungsi yang dapat melempar eksepsi harus menanganinya melalui try-catch atau mendeklarasikan throws di tanda tangan.

Bagaimana Try-Catch bekerja

Mekanisme eksekusi try-catch didasarkan pada stack unwinding. Ketika di dalam blok try sebuah eksepsi dilemparkan melalui operator throw (atau sebagai akibat dari kesalahan sistem), aliran eksekusi normal segera dihentikan. Eksekusi berpindah ke tingkat yang lebih tinggi dalam tumpukan panggilan untuk mencari blok catch yang sesuai. Bahasa modern mencari catch dengan tipe yang sesuai dengan tipe eksepsi yang dilemparkan, menggunakan mekanisme pencocokan tipe (type matching).

Jika catch yang sesuai ditemukan, tubuhnya dieksekusi, setelah itu eksekusi berlanjut setelah seluruh konstruksi try-catch-finally. Jika catch tidak ditemukan, eksepsi naik lebih jauh dalam tumpukan dan dapat ditangani di tingkat yang lebih tinggi — hingga handler global yang dalam aplikasi mobile menampilkan dialog kesalahan kepada pengguna. Jika eksepsi tidak ditangani di mana pun, aplikasi akan crash. Karena itulah penanganan yang benar dari semua tipe eksepsi yang mungkin sangat penting untuk stabilitas aplikasi.

Sintaks konstruksi dasar

kotlin
fun readUserData(): User {
    return try {
        val response = api.fetchUser()
        parseUser(response)
    } catch (e: IOException) {
        logError("Kesalahan jaringan", e)
        throw AppException("Gagal memuat data")
    } catch (e: JsonParseException) {
        logError("Kesalahan parsing", e)
        return User.default()
    } finally {
        closeLoadingIndicator()
    }
}

Kode pertama-tama mencoba mengeksekusi permintaan API dan mem-parse respons. Jika terjadi IOException (masalah jaringan), eksepsi dicatat dan diteruskan sebagai AppException. Jika JsonParseException — pengguna default dikembalikan. Blok finally secara terjamin menyembunyikan indikator pemuatan, mencegah kebocoran komponen UI di layar.

Try-Catch di Swift

Di Swift, penanganan kesalahan diimplementasikan melalui protokol Error (sebelumnya ErrorType). Tipe apa pun yang sesuai dengan Error dapat dilemparkan melalui operator throw. Fungsi yang dapat melempar kesalahan ditandai dengan kata kunci throws di tanda tangan. Pemanggilan fungsi semacam itu memerlukan prefiks try (untuk try-catch eksplisit), try? (hasil opsional) atau try! (eksekusi paksa tanpa penanganan kesalahan).

swift
enum NetworkError: Error {
    case noConnection
    case serverError(code: Int)
    case timeout
}

func fetchUser(id: Int) throws -> User {
    guard isConnected() else {
        throw NetworkError.noConnection
    }
    let data = try performRequest(path: "/users/\(id)")
    return try decodeUser(from: data)
}

do {
    let user = try fetchUser(id: 42)
    updateUI(user)
} catch NetworkError.noConnection {
    showOfflineAlert()
} catch let error as NetworkError {
    showError("Jaringan " + error.localizedDescription)
} catch {
    showGenericError()
}

Enum NetworkError mengimplementasikan protokol Error, mendefinisikan tiga kasus: noConnection, serverError dengan kode dan timeout. Fungsi fetchUser ditandai dengan throws: pertama memeriksa koneksi, kemudian mengeksekusi permintaan dan parsing. Di blok do-catch, tiga catch menangani skenario berbeda: kasus spesifik noConnection, tipe umum NetworkError dan semua kesalahan lainnya. Ini memungkinkan menampilkan pesan yang berbeda kepada pengguna tergantung pada jenis masalah.

Try-Catch di Kotlin

Kotlin mewarisi try-catch-finally dari Java, tetapi menambahkan perbedaan penting: di Kotlin, try-catch adalah sebuah ekspresi (expression), bukan pernyataan (statement). Ini berarti hasil dari blok try atau blok catch dapat ditetapkan ke variabel. Ekspresi terakhir di blok try menjadi hasil saat sukses, ekspresi terakhir di catch — saat kesalahan. Jika kesalahan tidak ditangani oleh catch mana pun, eksepsi diteruskan ke atas dalam tumpukan.

kotlin
sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
}

fun loadData(): Result<List<Item>> {
    return try {
        val response = api.getItems()
        Result.Success(response.toList())
    } catch (e: HttpException) {
        Log.e("HTTP ", e)
        Result.Error(e)
    } catch (e: IOException) {
        Log.e("Jaringan ", e)
        Result.Error(e)
    }
}

Dalam contoh, sealed class Result membungkus respons sukses atau kesalahan. Fungsi loadData menggunakan try-catch sebagai ekspresi: saat sukses mengembalikan Result.Success, saat eksepsi HttpException atau IOException — Result.Error dengan pencatatan. Pendekatan ini memungkinkan pihak pemanggil menangani kesalahan tanpa eksepsi — melalui ekspresi when berdasarkan tipe Result. Ini sangat nyaman di Jetpack Compose untuk menampilkan berbagai status UI (Loading, Success, Error) melalui StateFlow dan collectAsState.

Try-Catch di Dart dan Flutter

Dart mendukung try-catch-finally dengan sintaks yang mirip dengan Java, tetapi dengan tambahan klausa on untuk memfilter berdasarkan tipe eksepsi tanpa menentukan variabel. Ini nyaman ketika eksepsi itu sendiri tidak diperlukan — hanya fakta tipenya yang penting. Dart juga mendukung blok catch dengan dua parameter: objek eksepsi dan StackTrace, yang berguna untuk mencatat seluruh rantai panggilan.

dart
import 'dart:io';
import 'dart:convert';

class UserRepository {
    Future<User> fetchUser(String id) async {
        try {
            final client = HttpClient();
            final request = await client.getUrl(
                Uri.parse('https://api.example.com/users/$id')
            );
            final response = await request.close();
            final body = await response.transform(utf8.decoder).join();
            return User.fromJson(json.decode(body));
        } on SocketException catch (e, stackTrace) {
            log("No internet", e, stackTrace);
            throw AppException("Connection failed");
        } on FormatException {
            throw AppException("Invalid response format");
        } finally {
            client.close();
        }
    }
}

SocketException ditangkap dengan objek dan StackTrace untuk pencatatan detail, kemudian diteruskan sebagai AppException. FormatException ditangkap tanpa variabel — cukup mengetahui bahwa format respons tidak benar. Blok finally secara terjamin menutup HttpClient, mencegah kebocoran soket. Di Flutter, pendekatan ini sangat penting untuk pengujian Widget, di mana eksepsi yang tidak ditangani di State.initState menyebabkan kegagalan seluruh sesi pengujian.

Kesalahan umum saat menggunakan Try-Catch

Bahkan pengembang berpengalaman pun membuat kesalahan saat bekerja dengan try-catch yang menyebabkan kebocoran memori, bug tersembunyi atau perilaku aplikasi yang tidak tepat. Mari kita lihat lima masalah paling umum dalam pengembangan mobile.

Blok catch kosong

Catch kosong — salah satu praktik terburuk. Eksepsi ditelan, aplikasi terus berjalan dalam kondisi tidak benar, dan pengembang tidak mengetahui masalahnya. Selalu setidaknya catat eksepsi. Di Kotlin gunakan catch(e: Exception) { Log.e(...) }, di Swift — catch { print($0) }. Di Dart, catch minimal yang dapat diterima harus memanggil debugPrint atau menulis ke Crashlytics.

Catch terlalu luas

Menangkap semua eksepsi melalui catch (Exception e) tanpa membedakan berdasarkan tipe menyembunyikan kesalahan tak terduga — NullPointerException, OutOfMemoryError, StackOverflowError. Tangkap hanya tipe-tipe yang Anda harapkan dan dapat Anda tangani. Untuk sisanya, biarkan propagasi ke atas. Dalam pengembangan mobile, catch spesifik untuk IOException, TimeoutException, AuthException memberikan pesan yang lebih bermakna kepada pengguna.

Mengabaikan finally

Sumber daya — file, soket, kursor DB, animasi — harus dibebaskan di finally atau di blok use (AutoCloseable). Pengembang sering lupa menutup sumber daya saat eksepsi, yang menyebabkan kebocoran. Di Kotlin gunakan .use { } untuk sumber daya Closeable, di Swift — defer { }, di Dart — await using dari paket async. Blok finally menjamin pembebasan bahkan saat pelemparan eksepsi di dalam catch.

Eksepsi di thread dan coroutine

Dalam kode asinkron, try-catch tidak menangkap eksepsi dari thread lain. Di Kotlin Coroutines gunakan CoroutineExceptionHandler atau SupervisorJob. Di Swift async/await — do-catch di dalam Task. Di Flutter — runZonedGuarded untuk penangkapan global. Mengabaikan aturan ini adalah penyebab crash yang sulit direproduksi di produksi.

Memblokir UI saat eksepsi

Penanganan eksepsi tidak boleh memblokir antarmuka pengguna untuk waktu yang tidak ditentukan. Tampilkan pesan spesifik kepada pengguna dan berikan kemungkinan untuk mengulangi operasi. Snackbar dengan tombol Retry di Kotlin/Compose, UIAlertController dengan action di Swift, SnackBar dengan action di Flutter — UX minimal yang cukup untuk kesalahan jaringan atau server. Hindari dialog umum „Terjadi kesalahan" tanpa kemungkinan pemulihan.

Pertanyaan yang Sering Diajukan

Apa perbedaan try-catch dengan Result Type?

Try-catch menggunakan eksepsi dan stack unwinding untuk penanganan kesalahan, yang bisa mahal dari segi kinerja saat jumlah kesalahan besar. Result Type adalah tipe-kontainer (Success atau Failure) yang ditangani melalui pattern matching tanpa stack unwinding, lebih efisien untuk kesalahan yang diharapkan.

Apakah perlu menggunakan finally di setiap try-catch?

Finally wajib jika blok try membuka sumber daya (file, soket, kursor) yang perlu ditutup. Jika sumber daya tidak dibuka, finally tidak diperlukan. Di bahasa modern gunakan AutoCloseable/use/defer untuk penutupan sumber daya otomatis tanpa finally. Blok use di Kotlin dan Swift menggantikan finally untuk objek Closeable.

Bisakah try-catch menjadi lambat?

Dalam aliran normal (tanpa eksepsi), try-catch praktis tidak memengaruhi kinerja — JVM dan kompiler Swift mengoptimalkan kasus ini. Tetapi saat pelemparan eksepsi, terjadi stack unwinding yang bisa memakan waktu 10–100 µs tergantung kedalaman tumpukan. Jangan gunakan eksepsi untuk kontrol aliran eksekusi — ini adalah antipola.

Bagaimana menangani kesalahan di Kotlin Coroutines?

Di coroutine gunakan try-catch di dalam coroutineScope atau CoroutineExceptionHandler untuk penangkapan global. SupervisorJob mencegah pembatalan coroutine induk saat kesalahan di coroutine anak. Untuk launch gunakan CoroutineExceptionHandler, untuk async — try-catch di sekitar await().

Mana yang lebih baik: banyak catch atau satu catch dengan if-else?

Banyak catch lebih disukai: kode dibaca secara linear, setiap blok menangani satu tipe eksepsi. Satu catch dengan if-else lebih sulit dipelihara, mudah melewatkan tipe eksepsi baru. Di Swift, banyak catch wajib untuk penanganan lengkap enum Error, di Kotlin tidak ada batasan, tetapi praktik terbaik adalah catch terpisah per tipe.

Ringkasan

  • Try-Catch — konstruksi penangkapan eksepsi dengan blok try, catch dan finally opsional untuk pembebasan sumber daya yang terjamin
  • Mekanisme kerja — stack unwinding saat pelemparan eksepsi dengan pencarian catch yang sesuai berdasarkan tipe kesalahan
  • Di Swift menggunakan do-catch dengan enum Error, try? untuk hasil opsional dan try! untuk keberhasilan terjamin
  • Di Kotlin try-catch adalah ekspresi yang hasilnya dapat ditetapkan ke variabel, nyaman dipasangkan dengan sealed class Result
  • Di Dart mendukung klausa on untuk memfilter berdasarkan tipe tanpa variabel dan finally untuk menutup HttpClient
  • Kesalahan umum: catch kosong, penangkapan terlalu luas, mengabaikan finally dan kurangnya penanganan di coroutine
  • Gunakan try-catch untuk kesalahan tak terduga, Result Type — untuk skenario yang diharapkan dengan kemungkinan kegagalan

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga