Throw a Throws — mechanismy vyhazování a deklarace výjimek v programovacích jazycích. Operátor throw přerušuje normální provádění funkce a předává objekt chyby nahoru zásobníkem volání. Klíčové slovo throws v signatuře funkce varuje volající stranu o možnosti chyby, činící kód předvídatelným. Podle Kotlin Documentation (2026) je throw v Kotlinu výraz (expression), nikoli příkaz, což umožňuje jeho použití uvnitř when-bloků a elvis operátoru.
Hlavní body
Throw — je operátor, který generuje výjimku v místě provádění programu. Když narazí na throw, aktuální tok provádění je okamžitě přerušen a řízení je předáno nejbližšímu obslužnému prvku catch v zásobníku volání. Pokud obslužný prvek není nalezen, aplikace se abnormálně ukončí. Throw v mobilním vývoji se používá k signalizaci chyb, které nelze zpracovat na aktuální úrovni abstrakce — například nesprávná odpověď serveru, chybějící síť nebo neplatné argumenty.
Throws — modifikátor v signatuře funkce (hlavně ve Swiftu), který deklaruje, že funkce může vyhodit chybu. To je součást mechanismu checked errors ve Swiftu: volající strana je povinna zpracovat chybu prostřednictvím do-catch, try?, try! nebo označit svou funkci throws pro další předání (propagation). V Kotlinu a Javě throws také existuje, ale Kotlin jej považuje za nadbytečný — všechny výjimky v Kotlinu jsou unchecked, to znamená, že mohu zůstat nezpracované bez syntaktického donucení. Podle Apple Swift Documentation (2026) je throws ve Swiftu — jediným způsobem, jak explicitně deklarovat možnost chyby v typu funkce, což činí API kontrakty transparentními pro vývojáře.
Rozdíl mezi throw a throws je zásadní: throw — je činnost (vyhození výjimky za běhu), throws — je deklarace (smlouva v čase kompilace). Funkce bez throws nemůže použít throw — kompilátor Swiftu dá chybu. Funkce s throws nemusí throw použít — to je povoleno, ale nesmyslné. Toto oddělení činí throw/throws mocným nástrojem pro návrh API, kde je smlouva o chybě viditelná v signatuře funkce ještě před jejím voláním.
Ve Swiftu operátor throw přijímá jakýkoli typ implementující protokol Error. Nejčastěji je to enum s případy pro různé druhy chyb. Swift nepodporuje checked exceptions ve stylu Javy — místo toho je typ funkce označen throws a zpracování leží na volající straně. To činí throw ve Swiftu flexibilnějším, ale také zodpovědnějším pro vývojáře.
Jakýkoli typ, který vyhovuje protokolu Error, může být vyhozen pomocí throw. Nejčastěji vývojáři používají enum s případy bez přidružených hodnot (pro jednoduché chyby) nebo s associated values (pro předávání kontextu). Swift nevyžaduje, aby chyba byla enum — lze použít struct nebo class implementující Error, ale enum je upřednostňován díky exhaustive switch na straně obsluhy. Kompilátor kontroluje, že všechny případy jsou zpracovány v do-catch.
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 definuje tři scénáře: neplatné přihlašovací údaje, vypršený token a zablokovaný účet s přidruženou hodnotou remainingMinutes. Funkce login je deklarována jako throws — kompilátor vyžaduje její volání přes try. Uvnitř funkce je throw použito na dvou místech: při neplatném username a při zablokovaném účtu. Přidružená hodnota accountLocked umožňuje předat uživateli konkrétní údaje — kolik minut čekat do odblokování. Tento přístup eliminuje potřebu samostatných API endpointů pro kontrolu stavu blokování.
V Kotlinu je throw — výraz (expression) typu Nothing, nikoli přúkaz. To znamená, že throw lze použít na pravé straně přiřazení, uvnitř when výrazů a elvis operátoru ?:. Typ Nothing — speciální podtyp všech typů v Kotlinu, což umožňuje použití throw na místech, kde je vyžadována hodnota libovolného typu. Kompilátor chápe, že po throw provádění nepokračuje a nevyžaduje větev pro tento případ.
Nothing — jedinečný typ v Kotlinu, který je podtypem všech možných typů. Funkce vracející Nothing (například TODO()) se nikdy normálně neukončí — buď vždy vyhodí výjimku, nebo vstoupí do nekonečné smyčky. To činí throw přirozeným kandidátem pro použití na místech, kde je vyžadována hodnota: elvis operátor, when bez else, inicializace proměnné. Pokud je throw ve větvi when, kompilátor chápe, že větev vede k Nothing a nevyžaduje return nebo else pro tuto věev.
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")
}
}
}
V prvním příkladu je throw použito v elvis operátoru ?:: pokud pole apiUrl chybí v JSONu, výraz throw okamžitě přeruší provádění a vyhodí IllegalArgumentException. Typ Nothing umožňuje kompilátoru odvodit typ pravé strany jako String (elvis očekává String, throw má typ Nothing, Nothing je podtyp String). Ve druhém příkladu throw uvnitř when výrazu: pokud kód neodpovídá žádnému ze známých, vyhodí se výjimka. Kompilátor chápe, že po throw je kód nedosažitelný, takže návratový typ funkce String není porušen.
Ve Swiftu je throws uvedeno za seznamem parametrů a před šipkou návratového typu. Funkce s throws může volat pouze jiné throws funkce uvnitř do-catch nebo s try?. Pokud throws funkce nezpracovává chybu, předá ji volající straně. Swift také podporuje rethrows — modifikátor pro funkce vyššího řádu, které přijímají uzávěr (closure) s throws a propouštějí jeho chybu. Rethrows znamená, že funkce vyhodí chybu pouze pokud předaný uzávěr ji vyhodil — sama funkce chybu negeneruje.
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
}
// Použití s throws-uzávěrem
let parsed = try mapValues(jsonStrings) { str in
let data = Data(str.utf8)
return try JSONDecoder().decode(Item.self, from: data)
}
Rethrows umožňuje funkci mapValues být flexibilní: přijímá throws uzávěry i běžné. Pokud je předán throws uzávěr, volání mapValues vyžaduje try; pokud je běžný — try není potřeba. To činí rethrows ideálním pro funkce vyššího řádu jako map, filter, reduce ve standardní knihovně Swiftu. Doporučení Apple: používejte rethrows pro API, která přijímají throws uzávěry a jediným zdrojem chyby je tento uzávěr. Pokud funkce může vyhodit vlastní chybu, použijte throws.
Swift throws je bližší checked exceptions (jako v Javě) — vyhozené chyby jsou deklarovány v signatuře. Kotlin a Dart používají unchecked výjimky — throws v signatuře není vyžadováno. Rozdíl je zásadní: checked nutí vývojáře ke zpracování (bezpečnější, ale upovídanější), unchecked dává svobodu, ale zvyšuje riziko zapomenutí zpracovat chybu. Swift zvolil checked pro throws, Kotlin — unchecked pro všechny výjimky. Oba přístupy mají výhody: Swift je spolehlivější na úrovni jazyka, Kotlin je kompaktnější a pohodlnější v řetězcích funkcionálních transformací.
Pro strukturované zpracování chyb v mobilních aplikacích se doporučuje vytvářet vlastní typy chyb místo použití základních Exception nebo Error. Ve Swiftu se k tomu používá enum s protokolem Error, v Kotlinu — sealed class s dědičností od Throwable (nebo od Exception), v Dartu — class s dědičností od Exception. Vlastní typy umožňují seskupovat chyby podle kategorií a předávat přidružená data.
| Jazyk | Typ chyby | Vlastnost |
|---|---|---|
| Swift | enum: Error { ... } | Přidružené hodnoty, exhaustive switch v catch |
| Kotlin | sealed class : Throwable() | Data class pro chyby s poli, when výraz |
| Dart | class implements Exception | Pole Message, klauzule on v catch |
| Java | class extends Exception | Checked vs unchecked, povinný throws v signatuře |
Při navrhování vlastních chyb dodržujte pravidlo: jedna chyba — jeden scénář. Nekombinujte různé příčiny v jednom typu s příznakem String message — vytvářejte samostatné případy/podtřídy pro každý scénář. To umožní volající straně zpracovávat každý případ pomocí pattern matching (when/switch), nikoli porovnáváním řetězců. Ve Swiftu to dává exhaustive checking — kompilátor upozorní, pokud některý případ enum NetworkError není zpracován.
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 dědí od Throwable (standardní typ výjimek v Kotlinu). Každá podtřída je data class s vlastními poli: Timeout obsahuje dobu trvání čekaní v milisekundách, HttpError — kód a tělo odpovědi, NoConnection — původní IOException. Tento návrh umožňuje zpracování každé chyby pomocí when s úplným pokrytím (když přidáte novou podtřídu, kompilátor vás donutí aktualizovat všechny when výrazy).
Swift nabízí tři varianty volání throws funkcí, každá s vlastní bezpečnostní smlouvou. try — standardní způsob: vyžaduje do-catch nebo být uvnitř throws funkce. try? převádí chybu na nil — výsledek se stává volitelným, při chybě se vrací nil, typ se mění z T na T?. try! — vynucené provedení bez zpracování: pokud je chyba vyhozena, aplikace spadne. Používejte try! pouze když jste naprosto jisti, že chyba je nemožná (například zjevně správná data).
let configPath = Bundle.main.path(forResource: "config", ofType: "json")!
// try? — volitelný výsledek
let data = try? Data(contentsOf: URL(fileURLWithPath: configPath))
let json = try? JSONSerialization.jsonObject(with: data ?? Data())
// try! — zaručený úspěch (pouze když jste si jisti)
let decoder = JSONDecoder()
let defaultConfig = try! decoder.decode(
Config.self,
from: Config.defaultJSON
)
// try — standardní zpracování
do {
let user = try fetchUser()
showUser(user)
} catch let error as NetworkError {
showRetryAlert(error.message)
}
V příkladu je try! použito pro zjevně platný JSON vložený do bundle aplikace — chyba dekódování je při správném vydání nemožná. try? se aplikuje pro čtení konfiguračního souboru — pokud soubor chybí nebo je poškozen, aplikace použije výchozí hodnoty místo pádu. try v do-catch se používá pro síťové požadavky, kde je chyba očekávána a vyžaduje reakci uživatele. Doporučení: vyhněte se try! v produkčním kódu — vyjímku čiňte pouze pro konstantní data ověřená v průběhu sestavení.
Často kladené otázky
Throw — operátor, který vyhodí chybu během provádění programu a přeruší tok. Throws — modifikátor signatury funkce deklarující, že funkce může vyhodit chybu. Funkce bez throws nemůže použít throw. Throws je smlouva v čase kompilace, throw je činnost za běhu.
Kotlin následuje filozofii unchecked exceptions: všechny výjimky mohou být nezpracované bez syntaktického donucení. Vývojáři Kotlinu se domnívají, že throws v Javě vede k nadbytečným try-catch blokům a ignorování checked exceptions pomocí prázdných catch. Typ Nothing v Kotlinu umožňuje použít throw jako výraz a nahrazuje throws flexibilnějším způsobem.
try! je povoleno pouze když jste naprosto jisti, že chyba je nemožná: zjevně platný JSON z bundle, konstantní data, správné URL schéma. V produkčním kódu je try! výjimka, nikoli pravidlo. try? je upřednostňováno pro volitelné scénáře s výchozí hodnotou, try s do-catch pro povinné zpracování chyb.
Rethrows — modifikátor pro funkce, které přijímají throws uzávěry. Funkce s rethrows vyhodí chybu pouze pokud předaný uzávěr ji vyhodil. To umožňuje funkcím vyššího řádu (map, filter) pracovat s throws i non-throws uzávěry bez vynuceného try na volající straně.
Ano, uvnitř catch lze použít throw k propuštění chyby výše v zásobníku, zabalení do jiného typu nebo přidání kontextu. To se nazývá error chaining nebo rethrow. Ve Swiftu stačí další throw uvnitř catch, v Kotlinu — throw uvnitř bloku catch. Blok finally se provede před předáním řízení dále.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také