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 — 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
| Nyelv | Hibatípus | Jellemző |
|---|---|---|
| Swift | enum: Error { ... } | Társított értékek, exhaustive switch a catch-ben |
| Kotlin | sealed class : Throwable() | Data class hibákhoz mezőkkel, when-kifejezés |
| Dart | class implements Exception | Message mező, on-záradék a catch-ben |
| Java | class extends Exception | Checked 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.
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).
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).
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
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.
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.
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.
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.
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ó
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.
Olvassa el is