Try-Catch: esensya, konstruksyon ng pagkuha ng eksepsyon at kung paano ito gumagana sa mobile development

May-akda: IT Sectr Nai-publish: 2026-05-25 Oras ng pagbabasa: 9 min

Try-Catch — isang konstruksyon ng pagkuha ng eksepsyon na nagpapahintulot sa pagpapatupad ng potensyal na mapanganib na code sa isang protektadong bloke at tamang paghawak ng mga error nang hindi biglang nagtatapos ang programa. Ang bloke ng try ay naglalaman ng code na maaaring magtapon ng eksepsyon, hinuhuli ito ng catch at isinasagawa ang lohika ng pagbawi. Ayon sa Apple Swift Documentation (2026), ang bloke ng finally ay isinasagawa kahit na ang eksepsyon ay itinapon o hindi, na ginagarantiyahan ang pagpapalaya ng mga mapagkukunan.

Mga Pangunahing Punto

  • Try-Catch — konstruksyon para sa pagkuha ng eksepsyon na pumipigil sa biglang pagtatapos ng programa sa mga error
  • Bloke ng try ay naglalaman ng code na maaaring magtapon ng eksepsyon — ang pagpapatupad ay naaantala sa unang error
  • Bloke ng catch ay kumukuha ng eksepsyon ng tinukoy na uri at isinasagawa ang lohika ng paghawak o pagbawi
  • Bloke ng finally ay garantisadong isinasagawa pagkatapos ng try/catch para sa pagpapalaya ng mga mapagkukunan, halimbawa pagsara ng mga file
  • Nested try-catch ay nagpapahintulot sa paghawak ng mga error sa iba't ibang antas ng abstraksyon sa loob ng isang function

Ano ang Try-Catch?

Try-Catch — isang pangunahing konstruksyon ng nakabalangkas na paghawak ng eksepsyon, na naroroon sa karamihan ng mga modernong programming language. Binubuo ito ng tatlong bloke: try (pagtatangka na isagawa ang mapanganib na code), catch (pagkuha at paghawak ng eksepsyon) at opsyonal na finally (pagsasapinal). Ang ideya ng konstruksyon ay paghiwalayin ang lohika ng mga operasyon ng negosyo mula sa lohika ng paghawak ng error, na ginagawang mas nababasa at mahuhulaan ang code.

Ang konsepto ay unang ipinatupad sa wikang C++ bilang try/catch, pagkatapos ay pinagtibay ng Java, C#, Swift, Kotlin, Dart, Python, JavaScript at iba pang mga wika. Ang bawat wika ay nagdaragdag ng sarili nitong mga tampok: sa Swift ang bloke ng catch ay dapat na kumpleto, sa Kotlin ang try-catch ay maaaring isang expression, sa Dart ang finally ay sapilitan para sa mga mapagkukunan ng daloy. Sa kabila ng mga pagkakaiba, ang pangunahing prinsipyo ay pareho: ang error ay hinahawakan nang mas malapit hangga't maaari sa lugar ng pangyayari, hindi sa pandaigdigang antas.

Ang paggamit ng Try-Catch ay lalong mahalaga sa mobile development, kung saan ang mga panlabas na kadahilanan — pagkawala ng network, hindi tamang tugon ng server, kakulangan ng memorya — ay patuloy na nangyayari. Ang tamang paghawak ng eksepsyon ay pumipigil sa pag-crash ng application at tinitiyak ang tamang UX: ang user ay makakatanggap ng mensahe ng error sa halip na biglang pagsara ng application. Ayon sa Google Android Kotlin Style Guide (2026), ang bawat function na maaaring magtapon ng eksepsyon ay dapat alinman sa hawakan ito sa pamamagitan ng try-catch, o magdeklara ng throws sa lagda.

Paano gumagana ang Try-Catch

Ang mekanismo ng pagpapatupad ng try-catch ay batay sa stack unwinding. Kapag sa loob ng bloke ng try ay may itinapon na eksepsyon sa pamamagitan ng operator na throw (o bilang resulta ng error ng system), ang normal na daloy ng pagpapatupad ay agad na naaantala. Ang pagpapatupad ay lumilipat sa mas mataas na antas sa stack ng tawag upang maghanap ng angkop na bloke ng catch. Ang mga modernong wika ay naghahanap ng catch na may uri na tumutugma sa uri ng itinapon na eksepsyon, gamit ang mekanismo ng pagtutugma ng uri (type matching).

Kung ang angkop na catch ay natagpuan, ang katawan nito ay isinasagawa, pagkatapos kung saan ang pagpapatupad ay magpapatuloy pagkatapos ng buong konstruksyon na try-catch-finally. Kung ang catch ay hindi natagpuan, ang eksepsyon ay tumaas pa sa stack at maaaring hawakan sa mas mataas na antas — hanggang sa global handler na sa mobile application ay nagpapakita sa user ng isang dialog ng error. Kung ang eksepsyon ay hindi hinawakan kahit saan, ang application ay mag-crash. Ito ang dahilan kung bakit ang tamang paghawak ng lahat ng posibleng uri ng eksepsyon ay kritikal para sa katatagan ng application.

Sintaks ng pangunahing konstruksyon

kotlin
fun readUserData(): User {
    return try {
        val response = api.fetchUser()
        parseUser(response)
    } catch (e: IOException) {
        logError("Error sa network", e)
        throw AppException("Hindi na-load ang data")
    } catch (e: JsonParseException) {
        logError("Error sa parsing", e)
        return User.default()
    } finally {
        closeLoadingIndicator()
    }
}

Ang code ay unang sumusubok na isagawa ang isang kahilingan sa API at i-parse ang tugon. Kung magkaroon ng IOException (problema sa network), ang eksepsyon ay naka-log at ipinapasa bilang AppException. Kung JsonParseException — ang default na user ay ibabalik. Ang bloke ng finally ay garantisadong itatago ang indicator ng pag-load, na pumipigil sa pagtagas ng mga bahagi ng UI sa screen.

Try-Catch sa Swift

Sa Swift, ang paghawak ng error ay ipinatupad sa pamamagitan ng Error protocol (dating ErrorType). Anumang uri na umaayon sa Error ay maaaring itapon sa pamamagitan ng operator na throw. Ang function na maaaring magtapon ng error ay minarkahan ng keyword na throws sa lagda. Ang pagtawag sa naturang function ay nangangailangan ng prefix na try (para sa tahasang try-catch), try? (opsyonal na resulta) o try! (sapilitang pagpapatupad nang walang paghawak ng error).

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("Network " + error.localizedDescription)
} catch {
    showGenericError()
}

Enum NetworkError ay nagpapatupad ng Error protocol, na tumutukoy sa tatlong kaso: noConnection, serverError na may code at timeout. Ang function na fetchUser ay minarkahan ng throws: una nitong sinusuri ang koneksyon, pagkatapos ay isinasagawa ang kahilingan at pag-parse. Sa bloke ng do-catch, ang tatlong catch ay humahawak ng iba't ibang senaryo: ang tiyak na kaso na noConnection, ang pangkalahatang uri na NetworkError at lahat ng iba pang error. Ito ay nagpapahintulot sa pagpapakita ng iba't ibang mensahe sa user depende sa uri ng problema.

Try-Catch sa Kotlin

Ang Kotlin ay nagmana ng try-catch-finally mula sa Java, ngunit nagdagdag ng mahalagang pagkakaiba: sa Kotlin, ang try-catch ay isang expression, hindi isang statement. Ito ay nangangahulugan na ang resulta ng bloke ng try o bloke ng catch ay maaaring italaga sa isang variable. Ang huling expression sa bloke ng try ay nagiging resulta sa tagumpay, ang huling expression sa catch — sa error. Kung ang error ay hindi hinawakan ng anumang catch, ang eksepsyon ay ipapasa pataas sa stack.

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("Network ", e)
        Result.Error(e)
    }
}

Sa halimbawa, sealed class Result ay bumabalot ng matagumpay na tugon o error. Ang function na loadData ay gumagamit ng try-catch bilang expression: sa tagumpay ay nagbabalik ng Result.Success, sa eksepsyon na HttpException o IOException — Result.Error na may pag-log. Ang pamamaraang ito ay nagpapahintulot sa tumatawag na partido na hawakan ang mga error nang walang eksepsyon — sa pamamagitan ng when-expression batay sa uri ng Result. Ito ay lalong maginhawa sa Jetpack Compose para sa pagpapakita ng iba't ibang estado ng UI (Loading, Success, Error) sa pamamagitan ng StateFlow at collectAsState.

Try-Catch sa Dart at Flutter

Ang Dart ay sumusuporta sa try-catch-finally na may sintaks na katulad ng Java, ngunit may dagdag na on clause para sa pag-filter ayon sa uri ng eksepsyon nang hindi tinutukoy ang isang variable. Ito ay maginhawa kapag ang eksepsyon mismo ay hindi kailangan — ang katotohanan lamang ng uri nito ang mahalaga. Ang Dart ay sumusuporta rin sa bloke ng catch na may dalawang parameter: ang object ng eksepsyon at StackTrace, na kapaki-pakinabang para sa pag-log ng buong chain ng tawag.

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 ay nahuhuli gamit ang object at StackTrace para sa detalyadong pag-log, pagkatapos ay ipinapasa bilang AppException. FormatException ay nahuhuli nang walang variable — sapat na upang malaman na ang format ng tugon ay hindi tama. Ang bloke ng finally ay garantisadong isasara ang HttpClient, na pumipigil sa pagtagas ng socket. Sa Flutter, ang pamamaraang ito ay lalong mahalaga para sa pagsubok ng Widget, kung saan ang mga hindi nahahawakang eksepsyon sa State.initState ay humahantong sa pag-crash ng buong sesyon ng pagsubok.

Karaniwang pagkakamali sa paggamit ng Try-Catch

Kahit na ang mga bihasang developer ay nagkakamali sa pagtatrabaho sa try-catch na humahantong sa pagtagas ng memorya, mga nakatagong bug o hindi tamang pag-uugali ng application. Tingnan natin ang limang pinakakaraniwang problema sa mobile development.

Walang laman na bloke ng catch

Walang laman na catch — isa sa pinakamasamang kasanayan. Ang eksepsyon ay nilulunok, ang application ay patuloy na tumatakbo sa hindi tamang estado, at ang developer ay hindi alam ang problema. Palaging hindi bababa sa i-log ang eksepsyon. Sa Kotlin gamitin ang catch(e: Exception) { Log.e(...) }, sa Swift — catch { print($0) }. Sa Dart, ang pinakamababang katanggap-tanggap na catch ay dapat tumawag sa debugPrint o magsulat sa Crashlytics.

Masyadong malawak na catch

Ang pagkuha ng lahat ng eksepsyon sa pamamagitan ng catch (Exception e) nang hindi nag-iiba ayon sa uri ay nagtatago ng mga hindi inaasahang error — NullPointerException, OutOfMemoryError, StackOverflowError. Kunin lamang ang mga uri na iyong inaasahan at maaari mong hawakan. Para sa natitira, payagan ang pagpapalaganap pataas. Sa mobile development, ang tiyak na catch para sa IOException, TimeoutException, AuthException ay nagbibigay ng mas makabuluhang mensahe sa user.

Pagbalewala sa finally

Mga mapagkukunan — mga file, socket, cursor ng DB, animation — ay dapat palayain sa finally o sa bloke ng use (AutoCloseable). Madalas nakakalimutan ng mga developer na isara ang mga mapagkukunan sa eksepsyon, na humahantong sa pagtagas. Sa Kotlin gamitin ang .use { } para sa mga mapagkukunang Closeable, sa Swift — defer { }, sa Dart — await using mula sa package na async. Ang bloke ng finally ay ginagarantiyahan ang pagpapalaya kahit na sa pagtapon ng eksepsyon sa loob ng catch.

Mga eksepsyon sa mga thread at coroutine

Sa asynchronous na code, ang try-catch ay hindi kumukuha ng mga eksepsyon mula sa ibang mga thread. Sa Kotlin Coroutines gamitin ang CoroutineExceptionHandler o SupervisorJob. Sa Swift async/await — do-catch sa loob ng Task. Sa Flutter — runZonedGuarded para sa pandaigdigang pagkuha. Ang pagbalewala sa panuntunang ito ay sanhi ng mga crash na mahirap i-reproduce sa produksyon.

Pag-block ng UI sa eksepsyon

Ang paghawak ng eksepsyon ay hindi dapat harangan ang user interface para sa hindi tiyak na oras. Magpakita ng tiyak na mensahe sa user at magbigay ng posibilidad na ulitin ang operasyon. Snackbar na may button na Retry sa Kotlin/Compose, UIAlertController na may action sa Swift, SnackBar na may action sa Flutter — minimal na sapat na UX para sa mga error sa network o server. Iwasan ang mga pangkalahatang dialog na „May naganap na error" nang walang posibilidad ng pagbawi.

Mga Madalas Itanong

Ano ang pagkakaiba ng try-catch sa Result Type?

Ang try-catch ay gumagamit ng mga eksepsyon at stack unwinding para sa paghawak ng error, na maaaring magastos sa pagganap kapag maraming error. Result Type ay isang uri-container (Success o Failure) na hinahawakan sa pamamagitan ng pattern matching nang walang stack unwinding, mas mahusay para sa inaasahang mga error.

Kailangan bang gumamit ng finally sa bawat try-catch?

Ang finally ay sapilitan kung ang bloke ng try ay nagbubukas ng mga mapagkukunan (file, socket, cursor) na kailangang isara. Kung walang binubuksan na mapagkukunan, hindi kailangan ang finally. Sa mga modernong wika gamitin ang AutoCloseable/use/defer para sa awtomatikong pagsara ng mga mapagkukunan nang walang finally. Ang bloke ng use sa Kotlin at Swift ay pumapalit sa finally para sa mga bagay na Closeable.

Maaari bang maging mabagal ang try-catch?

Sa normal na daloy (walang eksepsyon), ang try-catch ay halos hindi nakakaapekto sa pagganap — na-optimize ng JVM at Swift compiler ang kasong ito. Ngunit sa pagtapon ng eksepsyon, nangyayari ang stack unwinding na maaaring tumagal ng 10–100 µs depende sa lalim ng stack. Huwag gumamit ng mga eksepsyon para sa kontrol ng daloy ng pagpapatupad — ito ay isang antipattern.

Paano hawakan ang mga error sa Kotlin Coroutines?

Sa mga coroutine gamitin ang try-catch sa loob ng coroutineScope o CoroutineExceptionHandler para sa pandaigdigang pagkuha. Pinipigilan ng SupervisorJob ang pagkansela ng magulang na coroutine sa error sa anak na coroutine. Para sa launch gamitin ang CoroutineExceptionHandler, para sa async — try-catch sa paligid ng await().

Alin ang mas mahusay: maramihang catch o isang catch na may if-else?

Ang maramihang catch ay mas gusto: ang code ay binabasa nang linear, ang bawat bloke ay humahawak ng isang uri ng eksepsyon. Isang catch na may if-else ay mas mahirap panatilihin, madaling makaligtaan ang bagong uri ng eksepsyon. Sa Swift, ang maramihang catch ay sapilitan para sa kumpletong paghawak ng enum Error, sa Kotlin walang limitasyon, ngunit ang pinakamahusay na kasanayan ay hiwalay na catch bawat uri.

Buod

  • Try-Catch — konstruksyon ng pagkuha ng eksepsyon na may mga bloke na try, catch at opsyonal na finally para sa garantisadong pagpapalaya ng mga mapagkukunan
  • Mekanismo ng paggana — stack unwinding sa pagtapon ng eksepsyon na may paghahanap ng angkop na catch ayon sa uri ng error
  • Sa Swift ay gumagamit ng do-catch na may enum Error, try? para sa opsyonal na resulta at try! para sa garantisadong tagumpay
  • Sa Kotlin ang try-catch ay isang expression na ang resulta ay maaaring italaga sa variable, maginhawa kasama ng sealed class Result
  • Sa Dart ay sumusuporta sa on clause para sa pag-filter ayon sa uri nang walang variable at finally para sa pagsara ng HttpClient
  • Karaniwang pagkakamali: walang laman na catch, masyadong malawak na pagkuha, pagbalewala sa finally at kawalan ng paghawak sa mga coroutine
  • Gamitin ang try-catch para sa hindi inaasahang mga error, Result Type — para sa inaasahang senaryo na may posibleng pagkabigo

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din