Throw/Throws — ano ito, mga operator ng paghagis ng exception at paano gumagana sa mobile development

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

Throw at Throws — mga mekanismo ng paghagis at deklarasyon ng exception sa mga programming language. Ang operator na throw ay humihinto sa normal na pag-execute ng function at nagpapasa ng error object pataas sa stack ng tawag. Ang keyword na throws sa signature ng function ay nagbabala sa tumatawag tungkol sa posibilidad ng error, na ginagawang predictable ang code. Ayon sa Kotlin Documentation (2026), ang throw sa Kotlin ay isang expression, hindi instruction, na nagpapahintulot gamitin ito sa loob ng when-blocks at elvis operator.

Mga pangunahing punto

  • Throw — operator na humihinto sa pag-execute ng function at nagpapasa ng error object pataas sa stack ng tawag
  • Throws — keyword sa signature ng function na nagdedeklara na ang function ay maaaring maghagis ng exception
  • Sa Swift ang function ay minamarkahan ng throws, ang tawag ay nangangailangan ng try/try?/try!, at ang throw ay tumatanggap ng anumang uri na nagpapatupad ng Error protocol
  • Sa Kotlin throw — expression ng uri na Nothing, wala ang throws (lahat ng exceptions ay unchecked)
  • Ang mga custom na error ay nilikha sa pamamagitan ng enum (Swift) o sealed class (Kotlin) para sa madaling pag-handle sa catch

Ano ang Throw at Throws?

Throw — ay ang operator na bumubuo ng exception sa punto ng pag-execute ng program. Kapag nakatagpo ang throw, ang kasalukuyang daloy ng pag-execute ay agad na nahihinto at ang kontrol ay inililipat sa pinakamalapit na handler ng catch sa stack ng tawag. Kung walang makitang handler, ang application ay nagtatapos nang abnormal. Ang throw sa mobile development ay ginagamit para magsenyas ng mga error na hindi mahawakan sa kasalukuyang antas ng abstraction — halimbawa, maling tugon ng server, walang network, o hindi wastong mga argumento.

Throws — modifikator sa signature ng function (pangunahin sa Swift) na nagdedeklara na ang function ay maaaring maghagis ng error. Ito ay bahagi ng mekanismo ng checked errors sa Swift: ang tumatawag ay obligadong hawakan ang error sa pamamagitan ng do-catch, try?, try! o markahan ang sariling function ng throws para sa karagdagang pagpapasa (propagation). Sa Kotlin at Java, umiiral din ang throws, ngunit itinuturing ito ng Kotlin na kalabisan — lahat ng exception sa Kotlin ay unchecked, ibig sabihin maaaring hindi mahawakan nang walang sintaktikong pagpilit. Ayon sa Apple Swift Documentation (2026), ang throws sa Swift — ay ang tanging paraan upang hayagang ideklara ang posibilidad ng error sa uri ng function, na ginagawang transparent ang mga kontrata ng API para sa developer.

Ang pagkakaiba sa pagitan ng throw at throws ay pundamental: throw — ay aksyon (paghagis ng exception sa runtime), throws — ay deklarasyon (compile-time contract). Ang function na walang throws ay hindi maaaring gumamit ng throw — ang Swift compiler ay magbibigay ng error. Ang function na may throws ay maaaring hindi gumamit ng throw — ito ay pinapayagan ngunit walang kahulugan. Ang paghihiwalay na ito ay ginagawang makapangyarihang kasangkapan ang throw/throws sa disenyo ng API, kung saan ang kontrata ng error ay nakikita sa signature ng function bago ito tawagin.

Throw sa Swift

Sa Swift ang operator na throw ay tumatanggap ng anumang uri na nagpapatupad ng Error protocol. Kadalasan ito ay isang enum na may cases para sa iba't ibang uri ng error. Hindi sinusuportahan ng Swift ang checked exceptions sa estilo ng Java — sa halip ang uri ng function ay minamarkahan ng throws, at ang pag-handle ay nasa panig ng tumatawag. Ginagawa nitong mas flexible ang throw sa Swift, ngunit mas responsable para sa developer.

Ang Error protocol at mga uri ng error

Anumang uri na umaayon sa Error protocol ay maaaring ihagis sa pamamagitan ng throw. Kadalasang gumagamit ang mga developer ng enum na may cases na walang associated values (para sa simpleng error) o may associated values (para sa pagpapasa ng konteksto). Hindi hinihingi ng Swift na ang error ay enum — maaaring gumamit ng struct o class na nagpapatupad ng Error, ngunit ang enum ay mas gusto dahil sa exhaustive switch sa panig ng handler. Sinusuri ng compiler na ang lahat ng cases ay nahawakan sa do-catch.

swift
enum AuthError: Error {
    case invalidCredentials
    case tokenExpired
    case accountLocked(remainingMinutes: Int)
}

func login(username: String, password: String) throws -> Session {
    guard isValid(username) else {
        throw AuthError.invalidCredentials
    }
    let response = try api.authenticate(username, password)
    if response.isLocked {
        throw AuthError.accountLocked(
            remainingMinutes: response.lockDuration
        )
    }
    return Session(token: response.token)
}

AuthError ay tumutukoy sa tatlong sitwasyon: hindi wastong credentials, expired na token, at naka-block na account na may associated value na remainingMinutes. Ang function na login ay idineklara bilang throws — hinihingi ng compiler na tawagin ito sa pamamagitan ng try. Sa loob ng function, ang throw ay ginagamit sa dalawang lugar: sa hindi wastong username at sa naka-block na account. Ang associated value na accountLocked ay nagpapahintulot na magpasa ng tiyak na data sa user — ilang minuto maghihintay hanggang ma-unblock. Ang pamamaraang ito ay nag-aalis ng pangangailangan para sa magkakahiwalay na API endpoints para suriin ang status ng pag-block.

Throw sa Kotlin

Sa Kotlin ang throw — ay expression ng uri na Nothing, hindi instruction. Ibig sabihin ang throw ay maaaring gamitin sa kanang bahagi ng assignment, sa loob ng when expression at elvis operator ?:. Ang uri na Nothing — espesyal na subtype ng lahat ng uri sa Kotlin, na nagpapahintulot sa paggamit ng throw sa mga lugar kung saan kinakailangan ang halaga ng anumang uri. Naiintindihan ng compiler na pagkatapos ng throw ay hindi nagpapatuloy ang execution at hindi nangangailangan ng branch para sa kasong ito.

Ang Nothing type at ang papel nito sa komposisyon

Nothing — natatanging uri sa Kotlin na subtype ng lahat ng posibleng uri. Ang function na nagbabalik ng Nothing (halimbawa TODO()) ay hindi kailanman nagtatapos nang normal — alinman ay laging naghahagis ng exception o pumapasok sa walang katapusang loop. Ginagawa nito ang throw na natural na kandidato para sa paggamit sa mga lugar kung saan kinakailangan ang halaga: elvis operator, when na walang else, initialization ng variable. Kung ang throw ay nasa branch ng when, naiintindihan ng compiler na ang branch ay patungo sa Nothing at hindi nangangailangan ng return o else para sa branch na ito.

kotlin
data class Config(val apiUrl: String, val timeoutSec: Int)

class ConfigParser {
    fun parse(json: String): Config {
        val obj = JSONObject(json)
        val url = obj.optString("apiUrl")
            ?: throw IllegalArgumentException("apiUrl is required")
        val timeout = obj.optInt("timeoutSec", 30)
        return Config(url, timeout)
    }

    fun getErrorMessage(code: Int): String {
        return when (code) {
            404 -> "Not found"
            500 -> "Server error"
            else -> throw IllegalArgumentException("Unknown code: $code")
        }
    }
}

Sa unang halimbawa ang throw ay ginagamit sa elvis operator ?:: kung ang field na apiUrl ay wala sa JSON, ang throw expression ay agad na humihinto sa execution at naghahagis ng IllegalArgumentException. Ang uri na Nothing ay nagpapahintulot sa compiler na mahinuha ang uri ng kanang bahagi bilang String (inaasahan ng elvis ang String, ang throw ay may uri na Nothing, ang Nothing ay subtype ng String). Sa ikalawang halimbawa ang throw sa loob ng when expression: kung ang code ay hindi tumutugma sa alinman sa mga kilala, isang exception ang ihahagis. Naiintindihan ng compiler na pagkatapos ng throw ang code ay hindi maaabot, kaya ang ibinalik na uri ng function na String ay hindi nilalabag.

Throws sa signature ng function at rethrows

Sa Swift ang throws ay tinutukoy pagkatapos ng listahan ng parameter at bago ang arrow ng ibinalik na uri. Ang function na may throws ay maaari lamang tumawag ng iba pang throws function sa loob ng do-catch o may try?. Kung ang throws function ay hindi humahawak ng error, ipinapasa nito ito sa tumatawag. Sinusuportahan din ng Swift ang rethrows — modifikator para sa higher-order functions na tumatanggap ng closure na may throws at nagpapasa ng error nito. Ang rethrows ay nangangahulugan na ang function ay naghahagis lamang ng error kung ang ipinasa na closure ay naghagis nito — ang function mismo ay hindi bumubuo ng error.

swift
func mapValues<T>(
    _ array: [T],
    transform: (T) throws -> U
) rethrows -> [U] {
    var result = [U]()
    for element in array {
        result.append(try transform(element))
    }
    return result
}

// Paggamit sa throws-closure
let parsed = try mapValues(jsonStrings) { str in
    let data = Data(str.utf8)
    return try JSONDecoder().decode(Item.self, from: data)
}

Rethrows ay nagpapahintulot sa function na mapValues na maging flexible: tinatanggap nito ang parehong throws closures at ordinary. Kung ang throws closure ay ipinasa, ang tawag sa mapValues ay nangangailangan ng try; kung ordinary — hindi kailangan ang try. Ginagawa nitong perpekto ang rethrows para sa higher-order functions tulad ng map, filter, reduce sa standard library ng Swift. Rekomendasyon ng Apple: gamitin ang rethrows para sa mga API na tumatanggap ng throws closures at ang tanging pinagmumulan ng error ay ang closure na ito. Kung ang function ay maaaring maghagis ng sarili nitong error, gamitin ang throws.

Checked vs unchecked exceptions

Ang Swift throws ay mas malapit sa checked exceptions (tulad ng sa Java) — ang mga inihagis na error ay idineklara sa signature. Ang Kotlin at Dart ay gumagamit ng unchecked exceptions — ang throws sa signature ay hindi kinakailangan. Ang pagkakaiba ay pundamental: pinipilit ng checked ang developer na mag-handle (mas ligtas ngunit mas verbose), ang unchecked ay nagbibigay ng kalayaan ngunit pinapataas ang panganib na makalimutang hawakan ang error. Pinili ng Swift ang checked para sa throws, Kotlin — unchecked para sa lahat ng exception. Ang parehong approach ay may mga bentahe: ang Swift ay mas maaasahan sa antas ng wika, ang Kotlin ay mas compact at mas maginhawa sa mga chain ng functional transformations.

Mga custom na uri ng error

Para sa structured na pag-handle ng error sa mobile applications, inirerekomenda na gumawa ng sariling mga uri ng error sa halip na gamitin ang batayang Exception o Error. Sa Swift para dito ginagamit ang enum na may Error protocol, sa Kotlin — sealed class na may inheritance mula sa Throwable (o mula sa Exception), sa Dart — class na may inheritance mula sa Exception. Ang mga custom na uri ay nagpapahintulot sa pagpapangkat ng mga error ayon sa kategorya at pagpapasa ng mga kaugnay na data.

WikaUri ng errorKatangian
Swiftenum: Error { ... }Mga associated value, exhaustive switch sa catch
Kotlinsealed class : Throwable()Data class para sa error na may fields, when expression
Dartclass implements ExceptionMessage field, on clause sa catch
Javaclass extends ExceptionChecked vs unchecked, mandatory throws sa signature

Sa pagdisenyo ng custom na error sundin ang patakaran: isang error — isang scenario. Huwag pagsamahin ang iba't ibang dahilan sa isang uri na may flag na String message — gumawa ng hiwalay na cases/subclasses para sa bawat scenario. Ito ay magpapahintulot sa tumatawag na hawakan ang bawat kaso sa pamamagitan ng pattern matching (when/switch), hindi sa pamamagitan ng paghahambing ng string. Sa Swift ito ay nagbibigay ng exhaustive checking — babalaan ng compiler kung ang isang case ng enum NetworkError ay hindi nahawakan.

Halimbawa ng custom na error sa Kotlin

kotlin
sealed class NetworkError(val message: String) : Throwable(message) {
    data class Timeout(val durationMs: Long) :
        NetworkError("Request timed out after ${durationMs}ms")
    data class HttpError(val code: Int, val body: String?) :
        NetworkError("HTTP $code")
    data class NoConnection(val cause: IOException) :
        NetworkError("No internet connection")
}

Ang Sealed class na NetworkError ay nagmamana mula sa Throwable (standard na uri ng exception sa Kotlin). Bawat subclass ay data class na may sariling fields: ang Timeout ay naglalaman ng tagal ng timeout sa millisecond, HttpError — code at body ng tugon, NoConnection — orihinal na IOException. Ang ganitong disenyo ay nagpapahintulot sa pag-handle ng bawat error sa pamamagitan ng when na may kumpletong coverage (kapag nagdagdag ka ng bagong subclass, pipilitin ka ng compiler na i-update ang lahat ng when expression).

Try, try? at try! sa Swift

Nag-aalok ang Swift ng tatlong variant ng pagtawag sa throws functions, bawat isa ay may sariling kontrata ng seguridad. try — karaniwang paraan: nangangailangan ng do-catch o nasa loob ng throws function. try? ginagawang nil ang error — ang resulta ay nagiging optional, sa error ay ibinabalik ang nil, ang uri ay nagbabago mula T patungong T?. try! — sapilitang execution nang walang pag-handle: kung ang error ay ihagis, ang application ay mag-crash. Gamitin ang try! lamang kapag lubos kang sigurado na imposible ang error (halimbawa, halatang wastong data).

swift
let configPath = Bundle.main.path(forResource: "config", ofType: "json")!

// try? — opsyonal na resulta
let data = try? Data(contentsOf: URL(fileURLWithPath: configPath))
let json = try? JSONSerialization.jsonObject(with: data ?? Data())

// try! — garantisadong tagumpay (kapag sigurado)
let decoder = JSONDecoder()
let defaultConfig = try! decoder.decode(
    Config.self,
    from: Config.defaultJSON
)

// try — karaniwang pag-handle
do {
    let user = try fetchUser()
    showUser(user)
} catch let error as NetworkError {
    showRetryAlert(error.message)
}

Sa halimbawa ang try! ay ginagamit para sa halatang wastong JSON na naka-embed sa bundle ng application — ang error sa decoding ay imposible sa tamang release. Ang try? ay inilalapat para sa pagbabasa ng configuration file — kung ang file ay wala o nasira, ang application ay gumagamit ng default values sa halip na mag-crash. Ang try sa do-catch ay ginagamit para sa network requests kung saan ang error ay inaasahan at nangangailangan ng reaksyon ng user. Rekomendasyon: iwasan ang try! sa production code — mag-exception lamang para sa constant data na na-verify sa build stage.

Mga madalas itanong

Ano ang pagkakaiba ng throw at throws sa Swift?

Throw — operator na naghahagis ng error sa panahon ng pag-execute ng program, humihinto sa daloy. Throws — modifikator ng signature ng function na nagdedeklara na ang function ay maaaring maghagis ng error. Ang function na walang throws ay hindi maaaring gumamit ng throw. Ang throws ay compile-time contract, ang throw ay runtime action.

Bakit walang throws sa Kotlin?

Ang Kotlin ay sumusunod sa pilosopiya ng unchecked exceptions: lahat ng exception ay maaaring hindi mahawakan nang walang sintaktikong pagpilit. Naniniwala ang mga developer ng Kotlin na ang throws sa Java ay humahantong sa labis na try-catch blocks at pagpapabaya sa checked exceptions sa pamamagitan ng empty catch. Ang Nothing type ng Kotlin ay nagpapahintulot sa paggamit ng throw bilang expression, na pinapalitan ang throws sa mas flexible na paraan.

Kailan gagamitin ang try! sa Swift?

Ang try! ay pinapayagan lamang kapag lubos kang sigurado na imposible ang error: halatang wastong JSON mula sa bundle, constant data, tamang URL schemes. Sa production code ang try! ay exception, hindi patakaran. Ang try? ay mas gusto para sa optional scenarios na may default na halaga, ang try na may do-catch para sa mandatoryong pag-handle ng error.

Ano ang rethrows sa Swift?

Rethrows — modifikator para sa mga function na tumatanggap ng throws closures. Ang function na may rethrows ay naghahagis lamang ng error kung ang ipinasa na closure ay naghagis nito. Ito ay nagpapahintulot sa higher-order functions (map, filter) na gumana sa parehong throws at non-throws closures nang walang sapilitang try sa panig ng tumatawag.

Maaari bang maghagis ng error sa loob ng catch block?

Oo, sa loob ng catch ay maaaring gumamit ng throw para ipalaganap ang error pataas sa stack, balutin ito sa ibang uri o magdagdag ng konteksto. Ito ay tinatawag na error chaining o rethrow. Sa Swift isa pang throw sa loob ng catch ay sapat, sa Kotlin — throw sa loob ng catch block. Ang finally block ay ie-execute bago ipasa ang kontrol sa susunod.

Buod

  • Throw — operator ng paghagis ng exception na humihinto sa kasalukuyang daloy at nagpapasa ng error object pataas sa stack
  • Throws — compile-time declaration sa signature ng function tungkol sa posibilidad ng error, mandatory sa Swift, wala sa Kotlin
  • Sa Swift throw ay tumatanggap ng enum: Error, ang function ay minamarkahan ng throws, tinatawag sa pamamagitan ng try / try? / try!
  • Sa Kotlin throw — expression ng uri na Nothing, nagpapahintulot ng paggamit sa when, elvis operator at assignments
  • Rethrows sa Swift ay nagpapahintulot sa higher-order functions na magpasa ng error lamang mula sa ipinasa na closures
  • Ang custom na error ay nilikha sa pamamagitan ng enum (Swift) o sealed class (Kotlin) na may associated values para sa detalyadong impormasyon
  • Idisenyo ang mga uri ng error batay sa prinsipyong isang case — isang scenario para sa madaling pag-handle sa pamamagitan ng pattern matching

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