Throw/Throws — mi ez, a kivételek dobásának operátorai és hogyan működnek a mobilfejlesztésben

Szerző: IT Sectr Megjelenés: 2026-05-26 Olvasási idő: 9 perc

Throw és Throws — a kivételek dobásának és deklarálásának mechanizmusai a programozási nyelvekben. A throw operátor megszakítja a függvény normál végrehajtását és továbbítja a hibaaobjektumot a hívási verem teteje felé. A throws kulcsszó a függvény szignatúrájában figyelmezteti a hívó felet a hiba lehetőségére, kiszámíthatóvá téve a kódot. A Kotlin Documentation (2026) szerint a throw Kotlinban egy kifejezés (expression), nem utasítás, ami lehetővé teszi a használatát when-blokkok és az elvis operátor belsejében.

Főbb pontok

  • Throw — operátor, amely megszakítja a függvény végrehajtását és továbbítja a hibaaobjektumot a hívási veremben felfelé
  • Throws — kulcsszó a függvény szignatúrájában, amely deklarálja, hogy a függvény kivételt dobhat
  • Swiftben a függvény throws-szal van jelölve, a hívás try/try?/try!-t igényel, a throw pedig bármilyen, az Error protokollt megvalósító típust elfogad
  • Kotlinban a throw — Nothing típusú kifejezés, throws nem létezik (minden kivétel unchecked)
  • Egyéni hibák enum (Swift) vagy sealed class (Kotlin) segítségével jönnek létre a catch-ben történő kényelmes kezelésért

Mi az a Throw és Throws?

Throw — az operátor, amely kivételt generál a program végrehajtási pontján. Amikor throw-al találkozik, a jelenlegi végrehajtási folyamat azonnal megszakad, és a vezérlés átadódik a legközelebbi catch-kezelőnek a hívási veremben. Ha nem található kezelő, az alkalmazás rendellenesen fejeződik be. A throw-t mobilfejlesztésben olyan hibák jelzésére használják, amelyek nem kezelhetők az aktuális absztrakciós szinten — például helytelen szerverválasz, hálózat hiánya vagy érvénytelen argumentumok.

Throws — módosító a függvény szignatúrájában (főleg Swiftben), amely deklarálja, hogy a függvény hibát dobhat. Ez a checked errors mechanizmus része Swiftben: a hívó fél köteles kezelni a hibát do-catch, try?, try! segítségével, vagy saját függvényét throws-szal jelölni a továbbításhoz (propagation). Kotlinban és Javában a throws szintén létezik, de a Kotlin feleslegesnek tartja — Kotlinban minden kivétel unchecked, azaz szintaktikai kényszer nélkül is kezeletlenül maradhat. A Apple Swift Documentation (2026) szerint a throws Swiftben — az egyetlen mód a hiba lehetőségének explicit deklarálására a függvény típusában, ami átláthatóvá teszi az API-szerződéseket a fejlesztő számára.

A throw és throws közötti különbség alapvető: a throw — egy cselekvés (kivétel dobása futási időben), a throws — egy deklaráció (fordítási idejű szerződés). A throws nélküli függvény nem használhat throw-t — a Swift fordító hibát ad. A throws-szal rendelkező függvény nem használhat throw-t — ez megengedett, de értelmetlen. Ez a szétválasztás a throw/throws-t hatékony eszközzé teszi az API-tervezésben, ahol a hibaszerződés a függvény szignatúrájában látható a hívás előtt.

Throw Swiftben

Swiftben a throw operátor bármilyen, az Error protokollt megvalósító típust elfogad. Leggyakrabban ez egy enum különbőző hibatípusokhoz tartozó esetekkel. A Swift nem támogatja a Java-stílusú checked exceptions-t — ehelyett a függvény típusa throws-szal van jelölve, és a kezelés a hívó fél felelőssége. Ez rugalmasabbá teszi a throw-t Swiftben, de egyben felelősségteijesebbé is a fejlesztő számára.

Az Error protokoll és hibatípusok

Bármely típus, amely megfelel az Error protokollnak, dobható throw segítségével. A fejlesztők leggyakrabban enum-ot használnak társított értékek nélküli esetekkel (egyszerű hibákhoz) vagy associated values-szal (kontextus átadásához). A Swift nem követeli meg, hogy a hiba enum legyen — használható struct vagy class, amely megvalósítja az Error-t, de az enum előnyben részesül a exhaustive switch miatt a kezelő oldalán. A fordító ellenőrzi, hogy az összes eset kezelve van-e a do-catch-ben.

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 három forgatókönyvet határoz meg: érvénytelen hitelesítő adatok, lejárt token és letiltott fiók a remainingMinutes társított értékkel. A login függvény throws-ként van deklarálva — a fordító megköveteli, hogy try-n keresztül legyen meghívva. A függvény belsejében a throw két helyen használatos: érvénytelen username-nél és letiltott fióknál. A társított érték accountLocked lehetővé teszi konkrét adatok átadását a felhasználónak — hány percet kell várnia a feloldásig. Ez a megközelítés kiküszöböli a külön API-végpontok szükségességét a letiltási állapot ellenőrzéséhez.

Throw Kotlinban

Kotlinban a throw — egy Nothing típusú kifejezés (expression), nem utasítás. Ez azt jelenti, hogy a throw használható az értékadás jobb oldalán, when-kifejezések belsejében és az elvis operátorban ?:. A Nothing típus — az összes típus speciális altípusa Kotlinban, ami lehetővé teszi a throw használatát olyan helyeken, ahol bármilyen típusú érték szükséges. A fordító megérti, hogy a throw után a végrehajtás nem folytatódik, és nem igényel ágat ehhez az esethez.

A Nothing típus és szerepe a kompozícióban

Nothing — egyedi típus Kotlinban, amely az összes lehetséges típus altípusa. A Nothing-ot visszaadó függvény (például TODO()) sosem fejeződik be normálisan — vagy mindig kivételt dob, vagy végtelen ciklusba lép. Ez a throw-t természetes jelöltté teszi azokon a helyeken, ahol érték szükséges: az elvis operátor, az else nélküli when, a változó inicializálása. Ha a throw egy when-ágban van, a fordító megérti, hogy az ág a Nothing-hoz vezet, és nem igényel return vagy else-t ehhez az ághoz.

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")
        }
    }
}

Az első példában a throw az elvis operátorban ?: használatos: ha az apiUrl mező hiányzik a JSON-ból, a throw kifejezés azonnal megszakítja a végrehajtást és IllegalArgumentException-t dob. A Nothing típus lehetővé teszi a fordító számára, hogy a jobb oldal típusát String-ként következtesse (az elvis String-et vár, a throw Nothing típusú, a Nothing a String altípusa). A második példában a throw when-kifejezés belsejében: ha a kód nem felel meg egyik ismertnek sem, kivétel dobódik. A fordító megérti, hogy a throw után a kód elérhetetlen, így a függvény String visszatérési típusa nem sérül.

Throws a függvény szignatúrájában és rethrows

Swiftben a throws a paraméterlista után és a visszatérési típus nyila előtt van megadva. A throws-szal rendelkező függvény csak más throws függvényeket hívhat do-catch-en belül vagy try?-vel. Ha egy throws függvény nem kezeli a hibát, továbbítja azt a hívó félnek. A Swift támogatja a rethrows-t is — egy módosítót magasabb rendű függvények számára, amelyek throws lezárást (closure) fogadnak és továbbítják annak hibáját. A rethrows azt jelenti, hogy a függvény csak akkor dob hibát, ha az átadott lezárás dobta — maga a függvény nem generál hibát.

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
}

// Használat throws-lezárással
let parsed = try mapValues(jsonStrings) { str in
    let data = Data(str.utf8)
    return try JSONDecoder().decode(Item.self, from: data)
}

Rethrows lehetővé teszi a mapValues függvény számára, hogy rugalmas legyen: mind throws lezárásokat, mind szokásosakat elfogad. Ha throws lezárás kerül átadásra, a mapValues hívása try-t igényel; ha szokásos — try nem szükséges. Ez a rethrows-t ideálissá teszi a magasabb rendű függvények, például a map, filter, reduce számára a Swift szabványkönyvtárában. Apple ajánlás: használjon rethrows-t az olyan API-khoz, amelyek throws lezárásokat fogadnak és a hiba egyetlen forrása ez a lezárás. Ha a függvény saját hibát dobhat, használjon throws-t.

Checked vs unchecked kivételek

A Swift throws közelebb áll a checked exceptions-höz (mint Javában) — a dobott hibák a szignatúrában vannak deklarálva. A Kotlin és Dart unchecked kivételeket használ — throws a szignatúrában nem kötelező. A különbség alapvető: a checked kényszeríti a fejlesztőt a kezelésre (biztonságosabb, de bőbeszédű), az unchecked szabadságot ad, de növeli a hiba elfelejtésének kockázatát. A Swift a checked-t választotta a throws-hoz, a Kotlin az unchecked-t minden kivételhez. Mindkét megközelítésnek vannak előnyei: a Swift megbízhatóbb nyelvi szinten, a Kotlin tömörebb és kényelmesebb a funkcionális transzformációk láncában.

Egyéni hibatípusok

A strukturált hibakezeléshez mobilalkalmazásokban ajánlott saját hibatípusok létrehozása az alap Exception vagy Error használata helyett. Swiftben ehhez enum-ot használnak az Error protokollal, Kotlinban — sealed class-t a Throwable-től (vagy Exception-től) való örökléssel, Dartban — class-t az Exception-től való örökléssel. Az egyéni típusok lehetővé teszik a hibák kategóriánkénti csoportosítását és a kapcsolódó adatok átadását.

NyelvHibatípusJellemző
Swiftenum: Error { ... }Társított értékek, exhaustive switch a catch-ben
Kotlinsealed class : Throwable()Data class hibákhoz mezőkkel, when-kifejezés
Dartclass implements ExceptionMessage mező, on-záradék a catch-ben
Javaclass extends ExceptionChecked vs unchecked, kötelező throws a szignatúrában

Az egyéni hibák tervezésekor kövesse a szabályt: egy hiba — egy forgatókönyv. Ne kombináljon különböző okokat egyetlen típusba String message jelzővel — hozzon lére külön eseteket/alkategóriákat minden forgatókönyvhez. Ez lehetővé teszi a hívó fél számára, hogy minden esetet pattern matching (when/switch) segítségével kezeljen, nem string-összehasonlítással. Swiftben ez exhaustive checking-et ad — a fordító figyelmeztet, ha a NetworkError enum valamely esete nincs kezelve.

Példa egyéni hibára Kotlinban

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")
}

Sealed class NetworkError a Throwable-ből (a Kotlin szabványos kivételtípusából) származik. Minden alkategória egy data class saját mezőkkel: a Timeout tartalmazza az időtúllépés időtartamát ezredmásodpercben, az HttpError — a válasz kódját és törzsét, a NoConnection — az eredeti IOException-t. Egy ilyen tervezés lehetővé teszi minden hiba kezelését when segítségével teljes lefedettséggel (amikor új alkategóriát ad hozzá, a fordító kényszeríti az összes when-kifejezés frissítésére).

Try, try? és try! Swiftben

A Swift három változatot kínál a throws függvények meghívására, mindegyik saját biztonsági szerződéssel. try — a szabványos mód: do-catch-t igényel vagy throws függvényen belül kell lennie. try? a hibát nil-lé alakítja — az eredmény opcionálissá válik, hiba esetén nil kerül visszaadásra, a típus T-ről T?-re változik. try! — kényszerített végrehajtás kezelés nélkül: ha hibát dobnak, az alkalmazás összeomlik. Csak akkor használja a try!-t, ha teljesen biztos abban, hogy a hiba lehetetlen (például nyilvánvalóan helyes adatok).

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

// try? — opcionális eredmény
let data = try? Data(contentsOf: URL(fileURLWithPath: configPath))
let json = try? JSONSerialization.jsonObject(with: data ?? Data())

// try! — garantált siker (csak ha biztos)
let decoder = JSONDecoder()
let defaultConfig = try! decoder.decode(
    Config.self,
    from: Config.defaultJSON
)

// try — szabványos kezelés
do {
    let user = try fetchUser()
    showUser(user)
} catch let error as NetworkError {
    showRetryAlert(error.message)
}

A példában a try! az alkalmazás bundle-jába ágyazott nyilvánvalóan érvényes JSON-hoz használatos — a dekódolási hiba lehetetlen helyes kiadás esetén. A try? konfigurációs fájl olvasására alkalmazandó — ha a fájl hiányzik vagy sérült, az alkalmazás alapértelmezett értékeket használ az összeomlás helyett. A try do-catch-ben hálózati kérésekhez használatos, ahol a hiba várható és felhasználói reakciót igényel. Ajánlás: kerülje a try!-t production kódban — csak a build szakaszban ellenőrzött állandó adatok esetében tegyen kivételt.

Gyakran ismételt kérdések

Mi a különbség a throw és a throws között Swiftben?

Throw — operátor, amely hibát dob a program futása során, megszakítva a folyamatot. Throws — a függvény szignatúrájának módosítója, amely deklarálja, hogy a függvény hibát dobhat. A throws nélküli függvény nem használhat throw-t. A throws fordítási idejű szerződés, a throw futási idejű cselekvés.

Miért nincs throws Kotlinban?

A Kotlin az unchecked exceptions filozófiáját követi: minden kivétel kezeletlenül maradhat szintaktikai kényszer nélkül. A Kotlin fejlesztői szerint a throws Java-ban túlzott try-catch blokkokhoz és a checked exceptions figyelmen kívül hagyásához vezet üres catch-eken keresztül. A Kotlin Nothing típusa lehetővé teszi a throw kifejezésként történő használatát, rugalmasabb módon helyettesítve a throws-t.

Mikor használja a try!-t Swiftben?

A try! csak akkor megengedett, ha teljesen biztos a hiba lehetetlenségében: nyilvánvalóan érvényes JSON a bundle-ból, állandó adatok, helyes URL-sémák. Production kódban a try! kivétel, nem szabály. A try? előnyben részesül opcionális forgatókönyvekhez alapértelmezett értékkel, a try do-catch-csel a kötelező hibakezeléshez.

Mi az a rethrows Swiftben?

Rethrows — módosító olyan függvények számára, amelyek throws lezárásokat fogadnak. A rethrows-szal rendelkező függvény csak akkor dob hibát, ha az átadott lezárás dobta. Ez lehetővé teszi a magasabb rendű függvények (map, filter) számára, hogy mind throws, mind non-throws lezárásokkal működjenek kényszerített try nélkül a hívó oldalán.

Lehet-e hibát dobni a catch blokkon belül?

Igen, a catch-en belül használható throw a hiba továbbítására a veremben felfelé, más típusba csomagolva vagy kontextust adva hozzá. Ezt error chaining-nek vagy rethrow-nak nevezik. Swiftben elegendő egy másik throw a catch-en belül, Kotlinban — throw a catch blokkon belül. A finally blokk a vezérlés továbbadása előtt fog lefutni.

Összefoglaló

  • Throw — kivételdobási operátor, amely megszakítja az aktuális folyamatot és továbbítja a hibaaobjektumot a veremben
  • Throws — fordítási idejű deklaráció a függvény szignatúrájában a hiba lehetőségéről, kötelező Swiftben, hiányzik Kotlinban
  • Swiftben a throw enum: Error-t fogad, a függvény throws-szal jelölt, try / try? / try! segítségével hívható
  • Kotlinban a throw — Nothing típusú kifejezés, lehetővé teszi a használatot when-ben, elvis operátorban és értékadásban
  • Rethrows Swiftben lehetővé teszi a magasabb rendű függvények számára, hogy csak az átadott lezárásokból továbbítsák a hibákat
  • Egyéni hibák enum (Swift) vagy sealed class (Kotlin) segítségével jönnek létre társított értékekkel a részletes információkhoz
  • Tervezze a hibatípusokat az egy eset — egy forgatókönyv elv alapján a pattern matching segítségével történő könnyű kezelésért

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is