Tworzenie własnych klas wyjątków
Definiuj wyjątki specyficzne dla domeny, wyposażone w zrozumiałe komunikaty i właściwości.
Tworzenie własnych klas wyjątków to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Po co własne wyjątki?
Własne wyjątki kodują znaczenie domenowe: wywołujący mogą przechwytywać je konkretnie, otrzymywać użyteczne komunikaty i reagować inaczej zależnie od typu.
Najprostszy własny wyjątek
Utwórz klasę dziedziczącą po Exception (lub po konkretnym podtypie, takim jak RuntimeException) i przekaż komunikat do konstruktora nadklasy.
class InvalidEmailException(message: String) : Exception(message)
fun main() {
try {
throw InvalidEmailException("missing @")
} catch (e: InvalidEmailException) {
println("caught: ${e.message}")
}
}Wyjątek z właściwościami
Dodaj pola przekazujące kontekst: kod statusu HTTP, nazwę pola, liczbę ponowień i inne informacje.
class HttpError(
message: String,
val statusCode: Int
) : Exception(message)
fun main() {
try {
throw HttpError("Not Found", 404)
} catch (e: HttpError) {
println("HTTP ${e.statusCode}: ${e.message}")
}
}Wyjątek z przyczyną
Przekaż cause, aby zachować pierwotny wyjątek w łańcuchu.
class DatabaseError(message: String, cause: Throwable) : Exception(message, cause)
fun main() {
try {
try { error("connection refused") }
catch (e: Throwable) { throw DatabaseError("query failed", e) }
} catch (e: DatabaseError) {
println("${e.message} (caused by: ${e.cause?.message})")
}
}Wyjątki sprawdzane a niesprawdzane
Kotlin traktuje wszystkie wyjątki jako niesprawdzane (nie trzeba deklarować throws). Zgodnie z konwencją dziedzicz po RuntimeException.
class ValidationException(field: String, message: String) :
RuntimeException("[$field] $message")
fun main() {
try {
throw ValidationException("age", "must be positive")
} catch (e: ValidationException) {
println(e.message)
}
}Hierarchia wyjątków domenowych
Utwórz hierarchię, aby wywołujący mogli przechwytywać typ bazowy w celu ogólnej obsługi albo konkretne podtypy w szczególnych przypadkach.
open class AppException(message: String) : RuntimeException(message)
class NotFoundException(what: String) : AppException("$what not found")
class UnauthorizedException : AppException("not authorized")
fun main() {
val errors = listOf(NotFoundException("user"), UnauthorizedException())
for (e in errors) {
try { throw e }
catch (e: AppException) { println("App error: ${e.message}") }
}
}Hierarchia wyjątków sealed
W przypadku zamkniętego zbioru typów błędów użyj hierarchii sealed — wywołujący mogą wyczerpująco obsłużyć każdy wariant.
sealed class ApiError(message: String) : RuntimeException(message) {
class Timeout : ApiError("timeout")
class NotFound(val id: String) : ApiError("not found: $id")
class ServerError(val status: Int) : ApiError("server returned $status")
}
fun describe(e: ApiError) = when (e) {
is ApiError.Timeout -> "request timed out"
is ApiError.NotFound -> "id ${e.id} missing"
is ApiError.ServerError -> "5xx: ${e.status}"
}
fun main() {
println(describe(ApiError.NotFound("user-42")))
}Konwencja nazewnicza
Dla jasności kończ nazwy własnych klas wyjątków przyrostkiem Exception lub Error. Używaj czasu przeszłego albo rzeczownika (np. NotFound, InvalidInput).
class InvalidInputException(msg: String) : RuntimeException(msg)
class UserNotFoundException(id: Int) : RuntimeException("user $id not found")
fun main() {
try { throw UserNotFoundException(7) }
catch (e: UserNotFoundException) { println(e.message) }
}Dokumentowanie wyjątków
Używaj w KDoc adnotacji @throws, aby udokumentować, jakie wyjątki może zgłaszać funkcja.
/**
* @throws InvalidEmailException if the email is malformed
*/
fun validate(email: String) {
if ("@" !in email) throw InvalidEmailException("missing @")
}
class InvalidEmailException(m: String) : RuntimeException(m)
fun main() {
try { validate("nope") }
catch (e: InvalidEmailException) { println(e.message) }
}Unikaj nadużywania wyjątków
Wyjątki służą do sytuacji wyjątkowych. W przypadku oczekiwanych wyników (puste dane wejściowe, brak opcjonalnego pola) preferuj zwracanie wartości null, typy wyników sealed albo wartości domyślne.
fun findUser(id: Int): String? = if (id == 1) "Alice" else null
fun main() {
val name = findUser(42) ?: "(unknown)"
println(name) // (unknown), no exception
}Praktyczny przykład
Realistyczny własny wyjątek dla fikcyjnego klienta API, zawierający kod statusu i treść odpowiedzi.
class ApiException(
message: String,
val statusCode: Int,
val responseBody: String
) : RuntimeException(message)
fun main() {
try {
throw ApiException("Bad Request", 400, "{\"error\":\"invalid\"}")
} catch (e: ApiException) {
println("[${e.statusCode}] ${e.message}: ${e.responseBody}")
}
}Szybkie sprawdzenie
Jaka klasa bazowa jest najczęściej używana podczas definiowania wyjątku domenowego w Kotlinie?
Podsumowanie
Własne wyjątki kodują znaczenie domenowe. Dziedzicz po RuntimeException lub Exception; dodawaj właściwości zapewniające kontekst; zachowuj przyczyny; twórz hierarchie na potrzeby grupowego przechwytywania. Używaj wyjątków sealed dla zamkniętych zbiorów i preferuj typy wartości null lub wyników, gdy błędy są oczekiwane.
Często zadawane pytania
Czy lekcja „Tworzenie własnych klas wyjątków” jest bezpłatna?
Tak — pełny tekst „Tworzenie własnych klas wyjątków” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Tworzenie własnych klas wyjątków”?
Definiuj wyjątki specyficzne dla domeny, wyposażone w zrozumiałe komunikaty i właściwości. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Tworzenie własnych klas wyjątków”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- try/catch/finally jako wyrażenie
- Tworzenie własnych klas wyjątków
- runCatching i Result
- Ponowne rzucanie wyjątków i ich łańcuchowanie