---
title: 'Null Güvenliği'
source: 'https://academia.sh/tr/kurslar/kotlin/null-guvenligi'
course: 'Kotlin Dili'
language: tr
updated: '2026-10-21T05:02:40+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'String ile String? arasındaki ayrımı derleyici reddi üzerinden gösterir'
    - 'Null denetiminden sonra akıllı tip dönüşümünün tipi daralttığını ölçer'
    - 'İki null değerin aynı nesne sayıldığını ve ölçütün tekil çıktığını gösterir'
    - 'Ölçütün ilk soruda durduğunu, sonraki sorulara bakılmadığını sınırlayıcı ölçümle doğrular'
---

# Null Güvenliği

Boş değer alabilen ve alamayan tiplerin ayrı tipler olduğunun, null denetiminden sonra tipin daraldığının ve null ile null eşitliğinin hangi ölçütü verdiğinin ölçümü.

Önceki ders kapsam fonksiyonlarının hangi değeri döndürdüğünü ölçtü. Döndürülen şey bazen hiçbir şeydir: bir arama sonuç bulamaz, bir alan doldurulmamıştır, bir dönüşüm tamamlanamaz. Bu durum bir değerle, örneğin `null` ile ifade edilebilir; o zaman o değerin her kullanımdan önce denetlenmesi gerekir ve denetim unutulduğunda hata çalışma anında ortaya çıkar.

Kotlin yokluğu tipin kendisine yazar. `String` her zaman bir dizgidir; `String?` ise ya bir dizgidir ya da `null`. Bu iki tip aynı tip değildir ve derleyici birini ötekinin yerine kullandırmaz. Buna **null güvenliği** denir: boş değer alabilen tip ile boş değer alamayan tip ayrı tiplerdir, dolayısıyla `null` olasılığı olan her yer kaynak kodda görünür. Bu ders o ayrımı derleyicinin vereceği red üzerinden ölçer, sonra aynı ayrımın eşitlik sorusuna ne söylediğine bakar.

Kursun ölçü ekseni, bir değerin kendisine eşit sayılan başka bir değerle ilişkisidir. Bir **ölçüt** dört biçimden birini alır: **tekil**, **kimlik**, **içerik** ve **kısmi içerik**. Kural sırayla işler. İlk değer ile ikizi aynı nesneyse ölçüt tekildir. Değilse ve ikiz eşit değilse kimliktir: yalnızca aynı nesne eşit sayılır. İkiz eşit ama ilkinden bir bakımdan ayrılan üçüncü değer eşit değilse içeriktir: nesneler ayrı, eşitlik içerikten gelir. Üçüncü değer de eşitse kısmi içeriktir: ayrılan bakım eşitliği etkilemez. Açılış dersindeki bağlayıcı ölçümde sekiz değerin dağılımı 2/2/3/1 idi; bu ders yalnız kendi kesitini ölçer.

Sınıflandırmayı yapan `Criterion` sınıfı aşağıda olduğu gibi verilir. Kod blokları yalnızca sandbox içinde derlenip koşturulur; çıktı bloklarındaki her satır sandbox'ın bastığıdır.

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

Parametreler `Any?` tipindedir; yani `null` da bir argüman olabilir. Bu dersin ilk sorusu tam olarak budur: `null` bir değer olarak ele alındığında hangi ölçütü verir?

## İki Ayrı Tip

Aşağıdaki blokta aynı içeriğe sahip bir `String` ve bir `String?` yan yana durur. Karşılaştırma derlenir, çünkü `==` iki tarafın tipini birbirine denk getirmeyi gerektirmez; yalnız içeriğe bakar. Ama uzunluk gibi tipe bağlı bir işlem yalnız boş değer alamayan tipte sorunsuzdur.

```kotlin
// Main.kt — iki tip
fun main() {
    val a: String = "kutu"
    val b: String? = "kutu"
    println(a == b)
    println(a.length)
    val c: String? = null
    println(c == null)
    println(c)
}
```

```
true
4
true
null
```

`a == b` doğrudur: iki dizgi aynı içeriği taşır ve `String?` tipinin dolu hâli bir dizgi olarak karşılaştırılır. `c` ise `null` taşır ve ekrana `null` yazılır; boş değer alabilen bir değişkenin yazdırılması bir hata değildir. Dikkat edilecek nokta, `a.length` satırında `a`'nın boş değer alamayan bir tip olmasıdır. Aynı satırı `b` ile yazmak derleyicinin reddine yol açar.

İki red vardır ve ikisi de sandbox'ta ölçüldü. Birincisi `String` tipli bir değişkene `null` atamaktır. Derleyici bunu Kotlin 2.4.21'de reddeder: `null` boş değer alamayan bir tipin değeri olamaz. Hata derleme sırasında çıkar, program hiç koşmaz.

```kotlin
fun main() {
    val text: String = null
    println(text)
}
```

İkincisi, `String?` tipli bir değişkende doğrudan `length` istemektir. Derleyici bunu da reddeder: alıcı boş değer alabilen bir tip olduğunda yalnızca güvenli çağrıya ya da null olmama iddiasına izin verilir. Güvenli çağrı bir sonraki dersin konusudur; null olmama iddiası da orada, hatasıyla birlikte ölçülür.

```kotlin
fun main() {
    val text: String? = "kutu"
    println(text.length)
}
```

**TN1.** Bu iki red yalnız yerel değişken için ölçüldü; sınıf özelliği, fonksiyon parametresi ya da dönüş tipi için ayrıca denenmedi. Hata metni derleyici sürümüne bağlıdır ve burada aktarılmaz; ölçülen şey, programın hiç koşmamasıdır.

## Null Denetiminden Sonra Tip Daralır

Bir `String?` değerinin uzunluğunu almak için önce `null` olmadığından emin olmak gerekir. Kotlin bunun için ayrı bir dönüştürme yazdırmaz. Bir `if` içinde `null` denetimi yapıldığında, o dalın içinde değişkenin tipi derleyici tarafından `String`'e daraltılır. Bu davranışa **akıllı tip dönüşümü** (`smart cast`) denir: programcı bir dönüştürme yazmaz, denetimin kendisi tipi değiştirir.

Aşağıdaki blokta `lengthOf` fonksiyonu `String?` alır; `if (text != null)` dalının içinde `text.length` doğrudan çağrılır. Blok ayrıca içinde iki `null` bulunan bir listeyi `filterNotNull` ile süzer; sonuç `List<String?>` değil `List<String>` olur ve elemanlar dönüştürme yapılmadan `length` verir.

```kotlin
// Main.kt — akilli tip donusumu
fun lengthOf(text: String?): Int {
    if (text != null) {
        return text.length
    }
    return -1
}

fun main() {
    println(lengthOf("kutu"))
    println(lengthOf(null))
    val values = listOf("a", null, "bb", null)
    println(values.size)
    val present = values.filterNotNull()
    println(present.size)
    println(present.sumOf { it.length })
}
```

```
4
-1
4
2
3
```

`lengthOf("kutu")` dört, `lengthOf(null)` ise `-1` verir. Liste dört elemanlıdır ama `filterNotNull` iki `null`'u atar ve geriye iki dizgi kalır; uzunluklarının toplamı üçtür. Burada ölçülen şey, `null` denetiminin yalnızca bir koşul olmadığıdır: denetimden sonra aynı değişken başka bir tiptir.

**TN2.** Akıllı tip dönüşümü yalnız `if` ve `filterNotNull` üzerinden ölçüldü; `when` içinde denetim, `&&` ile zincirlenen denetimler ve değiştirilebilir değişkenler için daralmanın ne zaman bozulduğu denenmedi. Daralma, denetimle kullanım arasında değişkenin değişmeyeceği bilindiği sürece geçerlidir.

## Soru İşareti Nereye Yazılır

`?` işareti bir tipin yalnızca bir yerine yazılabilir ve yeri anlamı değiştirir. `List<String?>` elemanları boş olabilen bir listedir: liste vardır, içindeki bazı yerler `null`'dur. `List<String>?` ise listenin kendisi boş olabilen bir tiptir: liste ya vardır ya da yoktur, ama varsa hiçbir elemanı `null` değildir. İkisi birbirinden bağımsızdır ve ikisi aynı anda da yazılabilir.

Aşağıdaki blok iki durumu yan yana koyar. Elemanları boş olabilen listenin boyutu doğrudan okunur, çünkü liste kendisi boş olamaz. Listenin kendisi boş olabilen tipte ise önce `null` denetimi gerekir; denetimden sonra aynı değişken `List<String>` olarak davranır ve `size` doğrudan çağrılır.

```kotlin
// Main.kt — soru isareti nereye yazilir
fun main() {
    val items: List<String?> = listOf("a", null)
    val maybeList: List<String>? = null
    println(items.size)
    println(maybeList == null)
    if (maybeList != null) {
        println(maybeList.size)
    } else {
        println("liste-yok")
    }
}
```

```
2
true
liste-yok
```

**TN3.** Bu ölçüm boş bir listeyi değil, hiç bulunmayan bir listeyi (`null`) ele alır; boş ama var olan bir listenin davranışı denenmedi. İki `?` işaretinin birlikte yazıldığı `List<String?>?` biçimi de ölçülmedi.

## null ile null

Kursun ölçü ekseninde asıl soru şudur: iki `null` aynı nesne midir? Kotlin'de `null` bir sınıfın örneği değil, tek bir değerdir. Her `null` ötekiyle aynıdır; birini diğerinden ayıracak bir kimlik yoktur. Dolayısıyla kimlik eşitliği (`===`) ve yapısal eşitlik (`==`) iki `null` için aynı yanıtı verir. Kural ilk soruda durur: ilk değer ile ikizi aynı nesneyse ölçüt tekildir ve geri kalan sorulara bakılmaz.

Aşağıdaki blokta dört gözlem vardır. İlk ikisinde ilk değer ile ikizi `null`'dur ve üçüncü değer birinde dolu, ötekinde yine `null`'dur. Üçüncü ve dördüncü gözlemde dolu dizgiler kullanılır: iki dizgi `buildString` ile ayrı ayrı kurulur, böylece aynı içeriği taşıyan iki ayrı nesne elde edilir.

```kotlin
// Main.kt — null ile null
fun main() {
    val nullFirst: String? = null
    val nullTwin: String? = null
    val full1 = buildString { append("ku"); append("tu") }
    val full2 = buildString { append("ku"); append("tu") }
    val checks = listOf(
        Criterion("null-null", nullFirst, nullTwin, "kutu"),
        Criterion("null-null-null", nullFirst, nullTwin, null),
        Criterion("dolu-dolu", full1, full2, "baska"),
        Criterion("dolu-null", full1, nullTwin, "baska"),
    )
    for (check in checks) check.report()
    summarize(checks)
}
```

```
null-null: ayni-nesne=true, ikiz=true, farkli=false -> tekil
null-null-null: ayni-nesne=true, ikiz=true, farkli=true -> tekil
dolu-dolu: ayni-nesne=false, ikiz=true, farkli=false -> icerik
dolu-null: ayni-nesne=false, ikiz=false, farkli=false -> kimlik
tekil: 2
kimlik: 1
icerik: 1
kismi-icerik: 0
```

Sonuç dört satırda okunur. `null` ile `null` tekildir. İki dolu dizgi, aynı içerikle ama ayrı nesneler olarak içerik ölçütünü verir: `ayni-nesne=false`, `ikiz=true`, `farkli=false`. Dolu bir dizgi ile `null` ise kimliktir: ikiz eşit değildir. Dolu dizgilerin ölçütü, bu derste yeniden tanımlanan hiçbir tipin değil, `String`'in kendi `equals`'inin sonucudur.

Burada bir tuzak vardır: iki `null`'un ölçütü tekil çıktı diye `null` ile karşılaştırılan her şeyin tekil olduğu sonucuna varılamaz. Tekil olan yalnızca `null` ile `null`'dur. Dolu bir değer `null`'a karşı kimliktir, çünkü ikiz eşit değildir.

**TN4.** Bu ölçüm yalnız `String?` tipli `null` değerleri için; başka tipli iki `null`'un aynı nesne sayılması denenmedi. Dolu dizgilerin ayrı nesne olduğu, `buildString` ile kurulduklarında `===` sonucundan okunmuştur; sabit dizgilerin aynı nesne olarak paylaşılıp paylaşılmadığı denenmedi.

## Null Olabilen Değer Üzerinde Hazır Fonksiyonlar

`null` denetimi her zaman bir `if` ile yazılmaz. Standart kitaplık, alıcısı `String?` olan birkaç fonksiyonu hazır sunar: `toString`, `isNullOrEmpty` ve `orEmpty`. Bu fonksiyonlar `null` alıcıda istisna fırlatmaz, çünkü tanımları alıcının `null` olabileceğini baştan hesaba katar. Aşağıdaki blok üç değerle (`null`, boş dizgi ve dolu dizgi) bu fonksiyonları dener. Bir de dizgiyle `null` toplandığında ne çıktığına bakar.

```kotlin
// Main.kt — null olabilen alici uzerinde hazir islevler
fun main() {
    val missing: String? = null
    val empty: String? = ""
    val present: String? = "ab"
    println(missing.toString())
    println("[" + missing + "]")
    println(missing.isNullOrEmpty())
    println(empty.isNullOrEmpty())
    println(present.isNullOrEmpty())
    println(missing == null)
    println(missing.orEmpty().length)
}
```

```
null
[null]
true
true
false
true
0
```

Çıktıdan üç şey okunur. Birincisi, `missing.toString()` istisna fırlatmaz; `null` alıcıda `"null"` dizgisini verir. İlk satırdaki `null` bu yüzden bir dizgidir, `null` değer değildir. İkincisi, dizgiyle `null` toplamak da çalışır ve sonuç `[null]` olur: `String.plus` argüman olarak `Any?` aldığı için derleyici itiraz etmez; boş olabilen taraf sağdaki argümandır. Üçüncüsü, `isNullOrEmpty` hem `null` hem boş dizgi için `true` döner, dolu dizgi için `false`; `orEmpty` ise `null`'ı boş dizgiye çevirdiği için uzunluk `0` çıkar.

Bu fonksiyonların ortak yanı alıcı tipinin `String?` olmasıdır. Sıradan bir `String` yöntemi bu tipte doğrudan çağrılamaz, çünkü alıcı yok olabilir. Sık yapılan hata, `toString` sonucunu `null` değerle karıştırmaktır. Sonucun tipi her zaman `String`'dir; bir değerin yokluğunu `"null"` dizgisini arayarak ölçmek yanlıştır. Yokluk `== null` ile sorulur. Dizgiyi günlüğe yazan kodda iki durumun aynı görünmesi, hatanın geç fark edilmesinin başlıca nedenidir.

## Tip Dönüşümü ve Null

Tip dönüşümü de `null` ile karşılaşır. `as` işleci dönüşümü zorlar, `as?` ise başarısız olunca `null` verir, `is` ise yalnızca soru sorar. Blok, değeri `null` olan bir `Any?` üzerinde üçünü dener; dönüşüm başarısız olursa fırlayan istisnanın yalnızca sınıf adı basılır. Son satırda dolu ama yanlış tipteki bir değer `as?` ile dönüştürülür.

```kotlin
// Main.kt — as ve as? null uzerinde
fun main() {
    val value: Any? = null
    println(value as? String)
    println(value is String)
    println(value is String?)
    try {
        val text = value as String
        println(text.length)
    } catch (e: Exception) {
        println(e::class.simpleName)
    }
    val other: Any? = 5
    println(other as? String)
}
```

```
null
false
true
NullPointerException
null
```

Üç ifade üç ayrı tavır sergiler. `as?` başarısız olduğunda istisna fırlatmaz, `null` verir; hem `null` değer hem de yanlış tipteki değer için sonuç `null`'dır. `is String` `null` için `false` döner, ama `is String?` `true` döner, çünkü `null` değeri `String?` tipinin bir üyesidir. Zorlayıcı `as String` ise `null` değerde `NullPointerException` fırlatır; blok bunu yakalayıp yalnızca sınıf adını basar.

Buradaki ders, iki `null` çıktısının aynı anlama gelmediğidir. İlk satırdaki `null`, dönüştürülecek değerin zaten yok olmasından gelir. Son satırdaki `null` ise değerin var olup tipinin uymamasından gelir ve yalnızca çıktıya bakarak bu ikisini ayırt etmek mümkün değildir. Ayrım gerekiyorsa dönüşümden önce `value == null` ayrıca sorulur. Dönüşümün zorlayıcı biçimi yalnızca tipin kesin bilindiği yerde yazılır; yanlış varsayım çalışma anında istisna olarak geri döner, derleme anında değil.

## Sınırlayıcı Ölçüm

Bu dersin kuralı şudur: ölçüt, ilk sorunun yanıtıdır. Kural dört soruyu sırayla sorar ve ilk "evet"te durur. Önceki bölümdeki ilk iki satır bunu zaten gösterdi, ama farkı açıkça görmek gerekir: `null-null` satırında üçüncü değer dolu (`"kutu"`), `null-null-null` satırında üçüncü değer `null`. Üçüncü değerin eşitliği (`farkli`) iki satırda zıt çıktı, ölçüt ise ikisinde de tekildir. `farkli=false` ile `farkli=true` arasında ölçütü değiştiren hiçbir şey yoktur; çünkü `Criterion` ilk soruda durur ve üçüncü değer ölçüte hiçbir bilgi katmaz.

Bu, sınırın nerede olduğunu gösterir. `farkli` sütunu basılır, çünkü `Criterion` üçüncü karşılaştırmayı her durumda hesaplar; ama tekil bir ölçütte o sütun okunmaz. Bir değerin tekil olduğunu söylemek, ona ne kadar çok değerin eşit olduğunu söylemez. Yalnızca ikizin aynı nesne olduğunu söyler.

Aynı sınır tersinden de okunur. İlk değer `null`, ikizi dolu bir dizgi olsaydı `ayni-nesne=false` ve `ikiz=false` çıkardı: ölçüt kimlik olurdu. Yani `null` ile başlamak ölçütü tekil yapmaz; tekil olmak için ikizin de `null` olması gerekir. Ölçütü belirleyen, ilk değerin tipi değil, ilk değer ile ikizinin aynı nesne olup olmadığıdır.

**TN5.** Sınırlayıcı ölçüm iki `null` ve bir dolu ya da `null` üçüncü değerle yapıldı; ilk değerin dolu, ikizin `null` olduğu sıralamanın ayrı bir çıktısı alınmadı, yalnızca `dolu-null` satırındaki kimlik sonucundan çıkarıldı. `Criterion`'ın kuralı başka sıralarla denenmedi.

## Özet

- `String` ile `String?` ayrı tiplerdir: `String`'e `null` atamak ve `String?` üzerinde doğrudan `length` istemek derlenmez.
- Bir `if` içindeki null denetimi, o dalda değişkenin tipini `String`'e daraltır; bu akıllı tip dönüşümüdür ve dönüştürme yazılmaz.
- `filterNotNull` bir `List<String?>`'i `List<String>`'e çevirir ve `null` elemanları atar.
- İki `null` aynı nesnedir ve ölçüt tekildir; dolu ayrı iki dizgi içerik, dolu dizgi ile `null` kimlik verir.
- Kural ilk soruda durur: ilk iki satırda üçüncü değerin eşitliği zıt çıktı, ölçüt aynı kaldı.
- Bu dersin ölçütü: **tekil**. `null` ile `null` aynı nesnedir.

## Sonraki Adım

Bu derste `null`'u tipte gördük ve `if` ile denetledik. Her `null` denetimi ayrı bir `if` ister ve denetimler art arda dizildikçe kod uzar. Bir sonraki ders aynı işi kısa yoldan yapan işleçleri ölçer: `?.` ile güvenli çağrı zinciri `null` gördüğünde nerede durur, `?:` ile Elvis işleci sağ tarafını ne zaman değerlendirir ve null olmama iddiası yanlış çıktığında hangi istisna fırlar.
