---
title: 'İstisna Yönetimi'
source: 'https://academia.sh/tr/kurslar/kotlin/istisna-yonetimi'
course: 'Kotlin Dili'
language: tr
updated: '2026-10-21T05:02:39+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "Kotlin'de istisna bildirmenin gerekmediğini ve try'ın değer üreten bir ifade olduğunu ölçer"
    - 'runCatching, Result, getOrElse ve exceptionOrNull ile hatayı değer olarak taşır'
    - 'coroutineScope içinde bir kardeşin başarısızlığının diğerini iptal edip dışarıya yayıldığını gösterir'
    - 'Aynı mesajla kurulan iki istisnanın eşit sayılmadığını ve veri sınıfı istisnanın içerikle karşılaştırıldığını ölçer'
---

# İstisna Yönetimi

Denetlenmeyen istisna modelinin, try ifadesinin, Result'ın ve eş yordamdaki yayılmanın ölçümü; aynı mesajlı iki istisnanın eşit sayılmadığının gösterilmesi ve kursun kapanışı.

Önceki ders iki akışın eşit sayılmadığını ölçtü. Bu son ders değer yerine bir hatanın eşit olup olmadığını sorar: aynı mesajı taşıyan iki istisna eşit midir? Önce Kotlin'in hata modeli okunur. Java'da bir fonksiyon hangi istisnaları fırlatabileceğini `throws` ile bildirir ve çağıran onları yakalamak zorundadır. Kotlin'de böyle bir bildirim yoktur; bütün istisnalar **denetlenmeyen istisna** sayılır, yakalamak çağıranın isteğine kalır. **Fırlatma** `throw` ile, **yakalama** `try` ve `catch` ile yapılır. Ölçü sorusu yine aynıdır: **bu iki değeri eşit yapan ne?**


```kotlin
// Criterion.kt — iki degeri esit yapan olcutu siniflandirir
class Criterion(val label: String, first: Any?, twin: Any?, other: Any?) {
    val sameObject = first === twin
    val equalTwin = first == twin
    val equalOther = first == other

    val name: String = when {
        sameObject -> "tekil"
        !equalTwin -> "kimlik"
        !equalOther -> "icerik"
        else -> "kismi-icerik"
    }

    fun report() {
        println("$label: ayni-nesne=$sameObject, ikiz=$equalTwin, farkli=$equalOther -> $name")
    }
}

fun summarize(checks: List<Criterion>) {
    for (name in listOf("tekil", "kimlik", "icerik", "kismi-icerik")) {
        println("$name: ${checks.count { it.name == name }}")
    }
}
```

## Denetlenmeyen İstisna ve try İfadesi

Aşağıdaki blok iki şeyi ölçer. `readDisk` Java'nın `IOException` istisnasını fırlatır, ama imzasında hiçbir bildirim yoktur ve derleyici bir şey istemez. `try` ise ifadedir: blok son ifadesinin değerini verir, `catch` dalı kendi değerini verir ve `finally` her durumda koşar ama değer üretmez. Günlük listesi sırayı gösterir.

```kotlin
// Main.kt — denetlenmeyen istisna, try ifadesi ve finally
import java.io.IOException

fun readDisk(): String {
    throw IOException("disk")
}

fun withdraw(balance: Int, amount: Int): Int {
    if (amount > balance) throw IllegalStateException("yetersiz")
    return balance - amount
}

fun main() {
    val log = mutableListOf<String>()
    val left = try {
        log.add("dene")
        withdraw(100, 500)
    } catch (e: IllegalStateException) {
        log.add("yakala")
        -1
    } finally {
        log.add("son")
    }
    println(left)
    println(log)
    try {
        readDisk()
    } catch (e: IOException) {
        println(e::class.simpleName)
    }
    println(withdraw(100, 30))
}
```

```
-1
[dene, yakala, son]
IOException
70
```

Birinci satır `-1`: `withdraw` fırlattığı için `try` bloğunun değeri atılıp `catch` dalının `-1` değeri `left`'e atandı. Günlük `[dene, yakala, son]` sırasını söyler; `finally` en sonda, değer belli olduktan sonra koştu. Üçüncü satır `IOException` adını verir; `catch` yazıldığı için yakalandı, yazılmasaydı da derleme geçerdi. Son satır fırlatmayan yolun `70` döndüğünü gösterir.

**KE35.** Bu ölçümler tek iş parçacıklı, `return` içermeyen `try` ifadeleri için. `finally` içinden `return` ya da yeni istisna fırlatmanın sonucu, `use` ile kaynak kapatma ve `Error` sınıfları ölçülmedi.

## runCatching ve Result

Hatayı yakalamak yerine değer olarak taşımak için `runCatching { }` kullanılır. Blok döndüyse `Result` başarılı, fırlattıysa başarısızdır. `getOrElse` başarısızlıkta yedek değeri verir, `exceptionOrNull` başarılıysa `null`, değilse istisnanın kendisini verir. Önce yardımcı dosyada **kendi istisna sınıfı** tanımlanır; ana blok onu fırlatan bir fonksiyon kurar.

```kotlin
// Errors.kt — kendi istisna sinifi
class LimitException(val limit: Int) : Exception("limit asildi")
```

```kotlin
// Main.kt — runCatching ve Result
fun parse(text: String): Int {
    if (text.length > 3) throw LimitException(3)
    return text.toInt()
}

fun main() {
    val ok = runCatching { parse("42") }
    val badFormat = runCatching { parse("x") }
    val tooLong = runCatching { parse("12345") }
    println(ok.getOrElse { -1 })
    println(badFormat.getOrElse { -1 })
    println(ok.exceptionOrNull())
    println(badFormat.exceptionOrNull()?.let { it::class.simpleName })
    val error = tooLong.exceptionOrNull()
    if (error is LimitException) {
        println(error.limit)
    }
}
```

```
42
-1
null
NumberFormatException
3
```

`ok` başarılı olduğu için `getOrElse` `42` verdi; `"x".toInt()` `NumberFormatException` fırlattığı için ikinci satır yedek değer olan `-1`. Üçüncü satır başarılı sonuçta `exceptionOrNull`'un `null` olduğunu, dördüncü satır başarısız sonuçta istisnanın tipini gösterir. Son satır kendi istisna sınıfının taşıdığı `limit` değerini okur: `is` denetimi sonrası `error` akıllı tip dönüşümüyle `LimitException` olur.

**KE36.** Bu ölçümler `Int` sonuçlu `runCatching` çağrıları ve `Exception` altındaki bir sınıf için. `map`, `recover` ve `onFailure` zincirleri, `getOrThrow` ve `Result`'ın fonksiyon dönüş tipi olarak kullanımı ölçülmedi.

## Eş Yordamda Yayılma

Yapılandırılmış eşzamanlılıkta bir çocuk eş yordam başarısız olursa kapsam iptal edilir: kardeşler iptal alır ve istisna `coroutineScope`'tan dışarı çıkar. Aşağıdaki blokta ilk çocuk bin milisaniye bekleyecek, ikincisi hemen fırlatacak. Dışarıda yakalanan istisnanın yalnız tipi basılır, mesajı basılmaz.

```kotlin
// Main.kt — eş yordamda istisnanın yayılması
import kotlinx.coroutines.*

fun main() = runBlocking {
    val log = mutableListOf<String>()
    val caught = try {
        coroutineScope {
            launch {
                try {
                    delay(1000)
                    log.add("bitti")
                } finally {
                    log.add("iptal")
                }
            }
            launch {
                throw IllegalStateException("kardes")
            }
        }
        "yok"
    } catch (e: Exception) {
        e::class.simpleName
    }
    println(caught)
    println(log)
}
```

```
IllegalStateException
[iptal]
```

Dışarıda yakalanan istisna çocuğun fırlattığı `IllegalStateException`'dır. Günlükte yalnız `iptal` vardır: bekleyen çocuğa iptal geldi, `finally` bloğu koştu ve `bitti` hiç yazılmadı. `coroutineScope` çağrısından sonraki `"yok"` satırına ise hiç gelinmedi. İstisna, eş yordamın kapsamını aşıp sıradan bir `try` ile yakalanabilir.

**KE37.** Bu ölçümler tek `coroutineScope`, tek `runBlocking` ve bir başarısız çocuk için. `supervisorScope`, `CoroutineExceptionHandler` ve birden çok başarısız çocuğun istisnalarının nasıl toplandığı ölçülmedi.

## Ölçüt: Kimlik

Şimdi asıl soru. Aynı mesajla kurulan iki istisna eşit midir? `Throwable` sınıfı `equals` tanımlamaz, kimliğe düşer. Sınırlayıcı ölçümler `Result`'ı ve veri sınıfı olarak yazılan bir istisnayı ekler. `Result.failure` içindeki istisnayı taşır: iki ayrı istisna iki ayrı `Result` yapar, aynı istisna iki `Result`'ı eşit yapar.

```kotlin
// Main.kt — istisnanın ölçütü ve sınırlayıcı ölçümler
data class CodedError(val code: Int) : Exception("kod")

fun main() {
    val shared = IllegalStateException("m")
    val checks = listOf(
        Criterion("istisna", IllegalStateException("m"), IllegalStateException("m"), IllegalStateException("x")),
        Criterion("sonuc-iki-istisna", Result.failure<Int>(IllegalStateException("m")), Result.failure<Int>(IllegalStateException("m")), Result.failure<Int>(IllegalStateException("x"))),
        Criterion("sonuc-ayni-istisna", Result.failure<Int>(shared), Result.failure<Int>(shared), Result.failure<Int>(IllegalStateException("x"))),
        Criterion("sonuc-basari", Result.success(1), Result.success(1), Result.success(2)),
        Criterion("veri-sinifi-istisna", CodedError(7), CodedError(7), CodedError(8)),
    )
    for (check in checks) check.report()
    summarize(checks)
}
```

```
istisna: ayni-nesne=false, ikiz=false, farkli=false -> kimlik
sonuc-iki-istisna: ayni-nesne=false, ikiz=false, farkli=false -> kimlik
sonuc-ayni-istisna: ayni-nesne=false, ikiz=true, farkli=false -> icerik
sonuc-basari: ayni-nesne=false, ikiz=true, farkli=false -> icerik
veri-sinifi-istisna: ayni-nesne=false, ikiz=true, farkli=false -> icerik
tekil: 0
kimlik: 2
icerik: 3
kismi-icerik: 0
```

İlk satır bu dersin ölçütüdür: aynı mesajlı iki istisna eşit değildir, ölçüt **kimlik**. İkinci satırda iki ayrı istisnayı saran `Result`'lar da eşit değildir. Üçüncü satırda aynı istisnayı saran iki ayrı `Result` nesnesi eşittir: `Result` istisnanın ölçütünü devralır. `Result.success(1)` iki kez içerik verir. Veri sınıfı olarak yazılan `CodedError` ise aynı koduyla eşittir, çünkü üretilen `equals`, `Exception`'dan devralınan kimlik eşitliğini yeniden tanımlar. Sınırlayıcı ölçüm şudur: **istisnanın ölçütünü tipi belirler, mesaj belirlemez.**

**KE38.** Bu ölçümler `IllegalStateException` ve `Result` için. İstisnanın `cause` zinciri, `stackTrace` içeriği ve `equals`'i yazılmış başka istisna sınıfları ölçülmedi.

## Özet

- Kotlin'de `throws` yoktur; bütün istisnalar denetlenmeyen istisnadır. `try` değer üreten bir ifadedir ve `finally` en sonda koşar.
- `runCatching` hatayı `Result` olarak taşır; `getOrElse` yedek değer, `exceptionOrNull` istisnayı verir.
- `coroutineScope` içinde bir çocuk başarısız olunca kardeşler iptal edilir ve istisna dışarıya yayılır.
- Aynı mesajlı iki istisna eşit değildir. Bu dersin ölçütü: **kimlik**.
- Sınırlayıcı ölçüm: `Result.failure` istisnanın ölçütünü taşır; veri sınıfı olarak yazılan istisna aynı alanla içeriktir.

## Kurs Kapanışı

Kurs yirmi üç dersle tek soruyu sordu ve her dersin ölçütü kaynak dersin özetinden alındı:

| Ders | Ölçülen değer | Ölçüt | Sınırlayıcı ölçüm |
|---|---|---|---|
| Kotlin'in Konumu | veri sınıfı, JVM listesi | içerik | kurucudaki `name` farklıysa eşit değil |
| Değişkenler | `const val` sabiti | tekil | çalışma anında kurulan aynı metin içerik |
| Temel Tipler | kutulanan `1000` | içerik | 127 tekil; NaN statik tipe göre değişir |
| Dizgi Şablonları | iki ayrı şablon | içerik | tek değişkenli şablon tekil |
| Denetim Akışı | `when` dalı, sıradan sınıf | kimlik | `is Box` tutar; iki `1..3` içerik |
| Fonksiyonlar | iki `::plain` | içerik | `listOf()` varsayılanı tekil |
| Lambdalar | iki ayrı lambda | kimlik | yakalamayan lambda tekil; `::inc` içerik |
| Kapsam Fonksiyonları | `let` ile `copy` | içerik | `also` ikizi tekil, ölçümü bozar |
| Null Güvenliği | `null` ile `null` | tekil | dolu iki dizgi içerik; dolu ile `null` kimlik |
| Güvenli Çağrı ve Elvis | iki güvenli çağrı | içerik | boş alıcıda iki `null` tekil |
| Sınıflar ve Yapıcılar | `equals`'siz sınıf | kimlik | aynı kalıp `equals`'e göre içerik, kısmi içerik |
| Veri Sınıfları | `copy` ile kurulan nesne | içerik | `IntArray` alanı kimlik, `List` alanı içerik |
| Mühürlü Tipler ve Numaralandırmalar | numaralandırma girdisi | tekil | alt tipin türü ölçütü belirler |
| Nesne Bildirimleri | iki okuma | tekil | nesne ifadesi her seferinde yeni, kimlik |
| Arayüzler ve Devretme | `by` ile devreden iki nesne | kimlik | aynı temsilcili iki veri sınıfı eşit |
| Uzantı Fonksiyonları | uzantı `equals` | kimlik | üye uzantıyı yener |
| Genellikler ve Varyans | iki boş liste, iki tip parametresi | tekil | genel veri sınıfı alan değerine bakar |
| Koleksiyon Türleri | liste eşitliği | içerik | küme sırası kısmi içerik; boş liste tekil |
| Dönüşüm İşlemleri | iki `map` | içerik | `distinct` öğenin ölçütünü kullanır |
| Tembel Diziler | iki `sequenceOf` | kimlik | `toList()` ile içerik |
| Eş Yordamlar | iki `Deferred` | kimlik | `await` sonuçları içerik |
| Akışlar | `distinctUntilChanged` | içerik | sıradan sınıfta 5 değer kalır; akış kimlik |
| İstisna Yönetimi | aynı mesajlı iki istisna | kimlik | `Result` istisnanın ölçütünü taşır; veri sınıfı istisna içerik |

Yirmi üç dersin dağılımı: tekil 5, kimlik 8, içerik 10, kısmi içerik 0. Kısmi içerik hiçbir dersin ölçütü olmadı; yalnız sınırlayıcı ölçümlerde göründü. Açılış dersinin çekirdeği ayrı bir sayımdır: sekiz değerin dağılımı 2/2/3/1'dir (tekil/kimlik/içerik/kısmi içerik). İkisi aynı şey değildir, çünkü çekirdek sekiz değer, tablo yirmi üç ders sayar.

Aynı mesajla kurulan iki istisnanın eşit çıkmaması, kursun bütün cevabını toplar: Kotlin'de eşitliği değerin görünüşü değil tipin kuralı verir. Sıradaki kurs Android Platformu ve Araçlar'dır; uygulamanın parçalarını ve bu parçaların yaşam döngülerini konu alır.
