---
title: "Kotlin'in Konumu"
source: 'https://academia.sh/tr/kurslar/kotlin/kotlinin-konumu'
course: 'Kotlin Dili'
language: tr
updated: '2026-10-21T05:02:40+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "Kotlin'in JVM üzerindeki konumunu ve statik tipli bir dil olarak amacını söylemek"
    - '`==` ve `===` işleçlerinin neyi karşılaştırdığını ayırt etmek'
    - 'Bir değerin eşitliğinin tekil, kimlik, içerik ya da kısmi içerik ölçütlerinden hangisine dayandığını sınıflandırmak'
---

# Kotlin'in Konumu

Kotlin'in JVM üzerindeki yerini ve tasarım hedeflerini tanıtır; aynı `==` işlecinin sekiz değerde dört ayrı ölçütle eşitlik verdiğini ölçer.

Bu kurs Kotlin'i bir dilin kendi sorusuyla öğretir: iki değer ne zaman aynıdır? Kotlin, statik tipli, derlenen bir programlama dilidir; JVM (Java Virtual Machine), Android, JavaScript, Wasm ve Native hedeflerine derlenir. Bu kurs ölçümlerini JVM hedefinde yapar: kaynak kodu bayt koduna çevrilir ve JVM'in kendi sınıf kitaplığıyla yan yana yaşar. Tasarım hedefleri iki cümlede toplanır: az törenle okunabilir kod yazmak ve tip denetimini derleme zamanına çekmek. Bu iki hedefin ortak noktası, dilin değerler hakkında kesin kurallar koymasıdır. İlk kurala hemen bakıyoruz: Kotlin'de `==` işleci eşitlik sorar, `===` işleci ise iki ifadenin aynı nesneye işaret edip etmediğini sorar.

Bu konunun sonraki yedi dersi aynı soruyu farklı yapılar üzerinde sorar. Her derste bir ölçüt bulunur ve bir sınırlayıcı ölçüm o ölçütün sınırını gösterir. Ölçüt dört addan biridir. **Tekil** (singleton) ölçüt, değerin bellekte tek bir örneği olduğu ve her yerden aynı nesneye ulaşıldığı durumdur. **Kimlik** ölçüt, eşitliğin nesnenin kendisine bağlı olduğu durumdur: aynı biçimde kurulmuş iki nesne eşit sayılmaz. **İçerik** ölçüt, eşitliğin taşınan değerlere bağlı olduğu durumdur. **Kısmi içerik** ölçüt, eşitliğin değerlerin yalnız bir bölümüne baktığı, geri kalanını yok saydığı durumdur.

## Sekiz Değer, Dört Ölçüt

Ölçüm her derste aynı yardımcı dosyayla yapılır. `Criterion` sınıfı bir değer ile onun aynı biçimde kurulmuş ikizini, bir de farklı bir değeri alır; üç soru sorar. İkiz aynı nesne mi? İkiz `==` ile eşit mi? Farklı değer `==` ile eşit mi? Bu üç yanıt dört ölçütten birini belirler.

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

Aşağıdaki program sekiz değeri bu sınıftan geçirir. Numaralandırma girdisi, nesne bildirimi, sıradan sınıf, dizi, veri sınıfı, liste, dizgi ve gövdesinde fazladan bir özellik taşıyan bir veri sınıfı. Veri sınıfı (data class), eşitliği ve metin gösterimini kurucu özelliklerinden türeten sınıftır; ayrıntısı bu dersin konusu değil, Veri Sınıfları dersinde işlenir; burada yalnız eşitliğine bakıyoruz.

```kotlin
// Main.kt — sekiz deger, dort olcut
enum class Color { RED, BLUE }

object Registry
object Archive

class Box(val size: Int)

data class Point(val x: Int, val y: Int)

data class Tag(val name: String) {
    var note: String = ""
}

fun main() {
    val word = listOf("kot", "lin").joinToString("")
    val checks = listOf(
        Criterion("numaralandirma-girdisi", Color.RED, Color.valueOf("RED"), Color.BLUE),
        Criterion("nesne-bildirimi", Registry, Registry, Archive),
        Criterion("siradan-sinif", Box(1), Box(1), Box(2)),
        Criterion("dizi", intArrayOf(1, 2), intArrayOf(1, 2), intArrayOf(1, 3)),
        Criterion("veri-sinifi", Point(1, 2), Point(1, 2), Point(1, 3)),
        Criterion("liste", listOf(1, 2), listOf(1, 2), listOf(1, 3)),
        Criterion("dizgi", "kotlin", word, "kotlim"),
        Criterion(
            "govdedeki-ozellik",
            Tag("a").apply { note = "ilk" },
            Tag("a").apply { note = "ilk" },
            Tag("a").apply { note = "son" },
        ),
    )
    for (check in checks) {
        check.report()
    }
    summarize(checks)
}
```

```
numaralandirma-girdisi: ayni-nesne=true, ikiz=true, farkli=false -> tekil
nesne-bildirimi: ayni-nesne=true, ikiz=true, farkli=false -> tekil
siradan-sinif: ayni-nesne=false, ikiz=false, farkli=false -> kimlik
dizi: ayni-nesne=false, ikiz=false, farkli=false -> kimlik
veri-sinifi: ayni-nesne=false, ikiz=true, farkli=false -> icerik
liste: ayni-nesne=false, ikiz=true, farkli=false -> icerik
dizgi: ayni-nesne=false, ikiz=true, farkli=false -> icerik
govdedeki-ozellik: ayni-nesne=false, ikiz=true, farkli=true -> kismi-icerik
tekil: 2
kimlik: 2
icerik: 3
kismi-icerik: 1
```

Çıktının okunuşu şöyledir. `numaralandirma-girdisi` ve `nesne-bildirimi` tekildir: numaralandırma girdisi (enum entry) ile `object` bildirimi bellekte tek örnek olarak yaşar, `Color.valueOf("RED")` çağrısı da aynı örneği döndürür. `siradan-sinif` ile `dizi` kimliktir: iki `Box(1)` aynı kurucu argümanını taşısa da eşit sayılmaz, iki `intArrayOf(1, 2)` de öyle. Dizide `==` elemanlara bakmaz, nesneyi karşılaştırır. `veri-sinifi`, `liste` ve `dizgi` içeriktir: ikizi eşittir, farklı değer eşit değildir ve ikizi aynı nesne değildir. Son satır, `govdedeki-ozellik`, kısmi içeriktir. `note` özelliği veri sınıfının kurucusunda değil gövdesinde tanımlı olduğu için eşitliğe katılmaz; `note` değeri `ilk` ile `son` olan iki nesne `==` ile eşit çıkar.

Özet satırları bu dağılımı doğrular: iki tekil, iki kimlik, üç içerik, bir kısmi içerik. Sekiz değerin tamamı sınıflandı ve hiçbiri beşinci bir ölçüte düşmedi.

**DT1.** Sekiz değerin her biri tek bir kurucu argümanı kümesiyle ölçüldü; aynı sınıfın başka argümanlarla kurulmuş örneklerinin sınıflandırması bu dersin dışındadır.

**DT2.** Dizi için yalnız `intArrayOf` ölçüldü; diğer dizi tiplerinin aynı davranışta olduğu bu derste ölçülmüş bir iddia değildir.

## JVM Üzerinde Kotlin

Kotlin JVM üzerinde çalıştığı için JVM'in kendi tiplerini doğrudan kullanır. `java.util.ArrayList` böyle bir tiptir. Kotlin'in `listOf` ile kurduğu liste de çalışma anında bir JVM listesidir; ikisi aynı eşitlik kuralına bağlıdır. Aşağıdaki blok üç şeyi ölçer: iki JVM listesini, bir Kotlin listesi ile bir JVM listesini ve kurucuya geçirilen değeri değiştirince veri sınıfının eşitliğini.

```kotlin
// Main.kt — JVM listesi ve ayni veri sinifi
import java.util.ArrayList

data class Tag(val name: String) {
    var note: String = ""
}

fun main() {
    val jvmList = ArrayList<Int>()
    jvmList.add(1)
    jvmList.add(2)
    val jvmTwin = ArrayList<Int>()
    jvmTwin.add(1)
    jvmTwin.add(2)
    println(jvmList.javaClass.name)
    val checks = listOf(
        Criterion("jvm-listesi", jvmList, jvmTwin, listOf(1, 3)),
        Criterion("kotlin-ve-jvm-listesi", listOf(1, 2), jvmList, listOf(1, 3)),
        Criterion("veri-sinifi-yapici", Tag("a"), Tag("a"), Tag("b")),
    )
    for (check in checks) {
        check.report()
    }
    summarize(checks)
}
```

```
java.util.ArrayList
jvm-listesi: ayni-nesne=false, ikiz=true, farkli=false -> icerik
kotlin-ve-jvm-listesi: ayni-nesne=false, ikiz=true, farkli=false -> icerik
veri-sinifi-yapici: ayni-nesne=false, ikiz=true, farkli=false -> icerik
tekil: 0
kimlik: 0
icerik: 3
kismi-icerik: 0
```

İlk satır JVM'in sınıf adını basar: `java.util.ArrayList`. `jvm-listesi` içeriktir, çünkü aynı elemanları taşıyan iki liste eşittir ve ayrı nesnelerdir. `kotlin-ve-jvm-listesi` de içeriktir: Kotlin'in `listOf(1, 2)` ifadesiyle kurduğu liste, bir JVM listesiyle elemanlar aynıysa `==` ile eşit çıkar. Kotlin tipi ile JVM tipi eşitlik açısından ayrı bir dünya oluşturmaz. `veri-sinifi-yapici` ise bu derste daha önce gördüğümüz `Tag` sınıfının kurucuya bağlı hâlidir; kurucudaki `name` farklı olunca eşitlik bozulur, yani eşitlik kurucu özelliklerine bakar.

**DT3.** Bu bölümde `listOf` ile `java.util.ArrayList` yalnız eşitlik açısından karşılaştırıldı; `listOf` ifadesinin çalışma anı sınıfı ilerideki bir bölümde ayrıca basılır.

**DT4.** JVM listesi `java.util.ArrayList` ile ölçüldü; JVM'in diğer koleksiyon sınıfları bu dersin dışındadır.

## Veri Sınıfının Türettikleri

Veri sınıfı, birincil yapıcıdaki özelliklerden `equals`, `hashCode`, `toString`, `componentN` ve `copy` üyelerini türetir; bu bölüm ilk üçünü ölçer. Önceki ölçüm yalnız `==` kolunu gösterdi. Aşağıdaki blok, gövdesinde `note` özelliği taşıyan bir `Tag` sınıfıyla üçünü birden sorar. İkinci nesnenin `note` değeri sonradan değiştirilir; kurucu argümanı iki nesnede de aynıdır.

```kotlin
// Main.kt — veri sinifi: equals, hashCode ve toString
data class Tag(val name: String) {
    var note: String = ""
}

fun main() {
    val first = Tag("a")
    val second = Tag("a")
    second.note = "ikinci"
    println(first == second)
    println(first.hashCode() == second.hashCode())
    println(first)
    println(second)
    println(first.note.isEmpty())
}
```

```
true
true
Tag(name=a)
Tag(name=a)
true
```

İlk iki satır `true` verir: `==` ve `hashCode` farkı görmez. Sonraki iki satır, `println` ile basılan gösterimin `note` değerini taşımadığını ortaya koyar. `second.note` artık `"ikinci"` olduğu hâlde ekrana `Tag(name=a)` çıkar. Son satır, `first.note` değerinin hâlâ boş olduğunu doğrular; yani iki nesne gerçekten farklı durumda ve türetilen üç davranış bu farkı birlikte yok sayar.

Sık yapılan hata tam burada çıkar. Bir hata ayıklama oturumunda iki nesneyi `println` ile basıp aynı görünce "bunlar aynı" sonucuna varılır; oysa gövdedeki özellik ayrı durur. Bu yüzden eşitliğe katılması gereken her değer kurucu özelliği olmalıdır. Java'da `equals` ve `hashCode` elle yazılır ve ikisinin birbiriyle tutarlı kalması geliştiricinin işidir; Kotlin'de ikisi aynı kurucu özelliklerinden birlikte türediği için, biri elle yeniden tanımlanmadıkça tutarsız kalmaz.

**DT5.** Java karşılaştırması bu bölümde ölçülmedi; Java tarafındaki `equals` ve `hashCode` yazımı bilinen davranış olarak anıldı, bu derste çalıştırılmış bir iddia değildir.

## Çalışma Anı Sınıfları

Kotlin kaynağında tek bir `Int` adı vardır; JVM'de ise `int` ilkeli ile `java.lang.Integer` kutusu ayrı iki şeydir. Aynı değerin çalışma anında hangi sınıfla yaşadığını `javaClass.name` ile okuyabiliriz. Blok beş değerin ve üç listenin sınıf adını basar.

```kotlin
// Main.kt — Kotlin degerlerinin JVM siniflari
fun main() {
    val number: Any = 1
    val text: Any = "kotlin"
    println(number.javaClass.name)
    println(text.javaClass.name)
    println(listOf(1, 2).javaClass.name)
    println(listOf(1).javaClass.name)
    println(emptyList<Int>().javaClass.name)
    println(mutableListOf(1).javaClass.name)
    println(intArrayOf(1).javaClass.name)
}
```

```
java.lang.Integer
java.lang.String
java.util.Arrays$ArrayList
java.util.Collections$SingletonList
kotlin.collections.EmptyList
java.util.ArrayList
[I
```

`Any` tipli tutulan `1`, `java.lang.Integer` olarak çıkar: değer bir `Any` değişkenine girince kutulanır. Dizgi `java.lang.String` olarak görünür; Kotlin'in ayrı bir dizgi sınıfı yoktur. `intArrayOf(1)` için sınıf adı `[I` çıkar, bu JVM'in `int[]` gösterimidir.

Listeler daha öğreticidir. `listOf(1, 2)` ifadesi `java.util.Arrays$ArrayList` verir, `listOf(1)` ise `java.util.Collections$SingletonList`. Boş liste için `kotlin.collections.EmptyList` çıkar. `mutableListOf(1)` ise `java.util.ArrayList` döndürür. Mekanizmanın nedeni şudur: `listOf` tek bir sınıf kurmaz, eleman sayısına göre en ucuz gerçekleştirmeyi seçer. Dolayısıyla bir `List` değerinin çalışma anı sınıfına güvenen kod kırılgandır: dört ayrı çağrı dört ayrı sınıf verdi. Eşitlik ise sınıf adına değil elemanlara dayanır; önceki bölümde `listOf` ile `java.util.ArrayList` içerik ölçütüyle eşit çıkmıştı.

Java karşılaştırması: Java'da `int` ile `Integer` kaynak kodda ayrı yazılır ve geliştirici kutulamayı kendisi seçer. Kotlin'de seçimi derleyici yapar. Bu gözlem `Any` tipli değişkenle ölçüldü; `Int?` tipinde de kutulama olacağı bu derste ölçülmedi.

**DT6.** Sınıf adları Kotlin 2.4.21 ve sandbox imajındaki JVM ile ölçüldü; başka bir JVM sürümünde `listOf` aynı iç sınıfları seçmeyebilir.

## Null ile Karşılaştırma

`==` işleci boş değer alabilen tiplerde de çalışır. Aşağıdaki blok boş bir `Tag?` ile dolu bir `Tag?` arasındaki beş karşılaştırmayı yapar.

```kotlin
// Main.kt — null ile karsilastirma
data class Tag(val name: String)

fun main() {
    val missing: Tag? = null
    val present: Tag? = Tag("a")
    println(missing == null)
    println(missing == present)
    println(present == Tag("a"))
    println(missing === missing)
    val none: String? = null
    println(none == none)
}
```

```
true
false
true
true
true
```

Beş satır sırayla şunları söyler. Boş değer `null` ile eşittir. Boş değer dolu bir nesneyle eşit değildir ve bu karşılaştırma bir hata fırlatmaz. Dolu nesne, aynı kurucu argümanıyla kurulmuş başka bir `Tag` ile eşittir. `===` null için de çalışır. İki boş dizgi birbirine eşittir.

Mekanizma şudur: `a == b` ifadesi, `a` boşsa `b`nin de boş olup olmadığını sorar; `a` doluysa `a.equals(b)` çağrılır. Derleyici bu null denetimini kendisi ekler. Sık yapılan hata, bu denetimi elle yazmaktır: `a != null && a.equals(b)` biçimindeki ifade fazladan söz taşır. Java'da `a.equals(b)` çağrısı `a` boş olduğunda `NullPointerException` fırlatır; Java'da null güvenli karşılaştırma için `Objects.equals` kullanılır. Kotlin'de aynı güvence `==` işlecinin kendisindedir.

**DT7.** Bu beş karşılaştırma `Tag` ve `String` üzerinde ölçüldü; Java tarafındaki `NullPointerException` davranışı ve `Objects.equals` anımsatma olarak yazıldı, bu derste çalıştırılmadı.

## Ölçümlerden Çıkan Alışkanlıklar

Bu dersin ölçümleri üç alışkanlığa bağlanabilir. Birincisi, bir sınıfın eşitlik davranışını tahmin etmek yerine ölçmektir. `Tag` veri sınıfı olduğu için iki ayrı örneği `==` ile eşit çıktı, ama `===` ile eşit çıkmadı; sıradan bir sınıfta ikisi de `false` verirdi. Bir sınıfı koleksiyonda anahtar olarak kullanacak ya da testte `assertEquals` ile karşılaştıracak kişi, önce bu iki işleç arasındaki farkı bilmelidir. Java'da `==` kimliğe, `equals` içeriğe bakar; Kotlin'de `==` içeriğe, `===` kimliğe bakar. Java'dan gelen biri `==` yazarken kimlik karşılaştırdığını sanabilir ve bu, dilleri ilk geçişte kod okumayı yanıltan bir noktadır.

İkincisi, çalışma anı sınıfına güvenmemektir. `listOf` çağrıları bu derste farklı JVM sınıfları üretti: tek öğeli liste, boş liste ve çok öğeli liste ayrı gerçekleştirimlerle geldi. Bu sınıf adları bir dil sözleşmesi değildir; Kotlin sürümü ya da hedef değiştiğinde değişebilir. Koda `list is ArrayList` gibi bir denetim yazmak, bu yüzden kırılgandır. Sözleşme, `List` arayüzünün kendisidir.

Üçüncüsü, `null` karşılaştırmasında okunur yazımı seçmektir. `==` ile `null` denetimi, nesnenin `equals` yöntemi çağrılmadan önce `null` durumunu ayrı ele alır; bu yüzden `null == null` doğrudur ve `x == null` yazımı `NullPointerException` fırlatmaz. Java'da `x.equals(y)` yazıldığında `x` boşsa istisna oluşur. Kotlin bunu işlecin tanımıyla kapatır ve ölçüm de beş karşılaştırmanın hiçbirinde istisna olmadığını gösterdi.

Bu üç alışkanlığın ortak yanı, ölçülmeden iddia edilmemesidir. Dersin geri kalanı bu ilkeyle ilerler: her iddia ya bir çıktıya dayanır ya da `DT` satırında "ölçülmedi" diye işaretlenir. Okuyucu için pratik sonuç şudur: bir davranıştan emin değilseniz, tek dosyalık küçük bir program yazıp çalıştırmak, belgeyi aramaktan daha kısa sürer. Bu kursta her dersin bir ölçütü olmasının nedeni de budur: ölçüt, hangi soruyu hangi işleçle sorduğunuzu baştan sabitler ve çıktıyı yorumlamayı kolaylaştırır. Veri sınıfı için içerik, sıradan sınıf için kimlik, tekil nesne için tekillik ölçütü geçerlidir. Bir tipin ölçütünü bilmek, o tiple yazılan her karşılaştırmanın ne anlama geldiğini bilmek demektir. Ölçütü yanlış varsayan kod çoğu zaman derlenir ve çalışır; hata ancak iki nesne beklenmedik biçimde eşit ya da farklı çıktığında görünür.

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

Ölçütün sınırı veri sınıfının içinde geçer. Aynı `Tag` sınıfı iki ölçütü birlikte taşır: kurucudaki `name` eşitliğe katılır, gövdedeki `note` katılmaz. `Tag("a")` ile `Tag("a")` içeriktir, `Tag("a")` ile `Tag("b")` eşit değildir; ama `name` aynı kalıp yalnız `note` değişince `==` yine `true` verir, yani kısmi içeriğe düşeriz. Bir sınıfın ölçütü bu yüzden sınıfın adından değil, `equals` davranışını hangi özelliklerden kurduğundan çıkar.

Bu iddiayı iki ölçümde gördük: `veri-sinifi-yapici` içeriktir, `govdedeki-ozellik` kısmi içeriktir.

## Özet

- Kotlin statik tipli, derlenen bir dildir; birden çok hedefe derlenir ve bu kursun ölçtüğü JVM hedefinde JVM tipleriyle doğrudan çalışır.
- `==` eşitliği, `===` ise nesne kimliğini sorar.
- Eşitlik dört ölçütten birine dayanır: tekil, kimlik, içerik, kısmi içerik.
- Veri sınıfının eşitliği kurucu özelliklerine bakar; gövdedeki özellik eşitliğe katılmaz.
- Bu dersin ölçütü: **içerik**; sınırlayıcı ölçüm: kurucudaki `name` farklı olunca aynı veri sınıfı eşit değildir.

## Sonraki Adım

Eşitliğin dört ölçütünü gördük. Sıradaki derste en küçük yapıdan başlıyoruz: bir değişkenin adı, tipi ve yeniden atanabilirliği. `val` ile `var` arasındaki fark, aynı değerin iki değişkende nasıl davrandığını da değiştirir mi, onu ölçeriz.
