---
title: Diziler
source: 'https://academia.sh/tr/kurslar/java-temelleri/diziler'
course: 'Java Temelleri'
language: tr
updated: '2026-08-17T18:09:40+00:00'
license: 'CC BY-SA 4.0'
---

# Diziler

Java'da dizi bir nesnedir ve ölçüm bunu üç yerde gösterir: üretim tek bir komut bırakır, `d.length` alan okuması değil kendi başına bir komuttur, sınır denetimi ile dizi kovaryansının tip denetimi ise sınıf dosyasında hiç görünmeden çalışma zamanına bırakılır.

Önceki ders akış biçimlerinin hangi komuta derlendiğini ölçtü: aynı seçim iki ayrı arama
komutuna, aynı gelişmiş `for` döngüsü dizide ve listede ayrı adıma dönüşüyordu. Geriye
üzerinde gezinilen şeyin kendisi kaldı.

Dizi, Veri Yapıları kursunda bir veri yapısı olarak kuruldu: sabit boyut, bitişik yerleşim,
konumdan adrese giden aritmetik. Bu ders onu tekrarlamaz. Buradaki soru şudur: `new int[3]`
satırı sınıf dosyasında kaç komut bırakır, `d.length` yazımı bir alan okuması mıdır, ve
dizinin sınırını denetleyen adım kaynağın neresinde durur? Üçünün de yanıtı, dizinin Java'da
bir **nesne** olmasından çıkar.

## Dizi Bir Nesnedir

- **SD21** — Ölçülen kaynak metni dersin içinde yazılır. Ne yazdığımızı bildiğimiz için,
  sınıf dosyasında bulunan her fazlalık derleyicinin eklediğidir.
- **SD22** — `Olcek` çekirdeği ortak tanımdan gelir. Bu ders ona yalnız bir ölçüm ekler:
  bir yöntemin komut adlarını sırayla döndüren `komutlar`. Var olan ölçümlerin davranışı
  değişmez.
- **SD23** — Komut adları sınıf dosyasındaki adlardır ve `Locale.ROOT` ile küçük harfe
  çevrilerek basılır; yerel ayar sonucu etkilemez.
- **SD24** — Derleyici sıfırdan farklı bir sonuç döndürürse çekirdek istisna fırlatır. Ders
  bu istisnayı yakalayıp yalnız "derlenmedi" satırını basar; derleyicinin ileti metni
  basılmaz.

```java
// Olcek.java — ortak ölçüm çekirdeği: derleyicinin sınıf dosyasına ne koyduğunu okur
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.classfile.*;
import java.lang.classfile.instruction.*;
import java.nio.file.*;
import java.util.*;
import java.util.spi.ToolProvider;

class Olcek {
    record Yontem(String ad, int komut, List<String> eklenen) {}
    record Sinif(List<Yontem> yontem, List<String> alan) {}

    static ClassModel derle(String kaynak, String sinif) throws Exception {
        Path d = Files.createTempDirectory("olcek");
        Path k = d.resolve(sinif + ".java");
        Files.writeString(k, kaynak);
        PrintWriter bos = new PrintWriter(Writer.nullWriter());
        if (ToolProvider.findFirst("javac").orElseThrow()
                .run(bos, bos, "-d", d.toString(), k.toString()) != 0)
            throw new IllegalStateException("derlenmedi: " + sinif);
        return ClassFile.of().parse(d.resolve(sinif + ".class"));
    }

    static Sinif oku(String kaynak, String sinif) throws Exception {
        ClassModel cm = derle(kaynak, sinif);
        List<Yontem> yontemler = new ArrayList<>();
        for (MethodModel m : cm.methods()) {
            if (m.code().isEmpty()) continue;
            List<String> eklenen = new ArrayList<>();
            int komut = 0;
            for (CodeElement e : m.code().get()) {
                if (e instanceof Instruction) komut++;
                if (e instanceof InvokeInstruction iv)
                    eklenen.add(kisa(iv.owner().asInternalName()) + "." + iv.name().stringValue());
                else if (e instanceof NewPrimitiveArrayInstruction a)
                    eklenen.add("yeni dizi " + a.typeKind().name().toLowerCase(Locale.ROOT));
                else if (e instanceof NewReferenceArrayInstruction a)
                    eklenen.add("yeni dizi " + kisa(a.componentType().asInternalName()));
            }
            yontemler.add(new Yontem(m.methodName().stringValue(), komut, eklenen));
        }
        List<String> alanlar = new ArrayList<>();
        for (FieldModel f : cm.fields()) alanlar.add(f.fieldName().stringValue());
        return new Sinif(yontemler, alanlar);
    }

    static List<String> komutlar(String kaynak, String sinif, String yontem) throws Exception {
        List<String> adlar = new ArrayList<>();
        for (MethodModel m : derle(kaynak, sinif).methods())
            if (m.methodName().stringValue().equals(yontem))
                for (CodeElement e : m.code().orElseThrow())
                    if (e instanceof Instruction i)
                        adlar.add(i.opcode().name().toLowerCase(Locale.ROOT));
        return adlar;
    }

    static String kisa(String ic) { return ic.substring(ic.lastIndexOf('/') + 1); }
}
```

```java
// Dizi.java — dizi üretimi sınıf dosyasında ne bırakıyor
import java.util.Arrays;

class Kayit {
    String ad;
    int adet;
    long agirlik;
}

public class Dizi {
    static final String K = """
        class DiziOrnek {
            static class Kayit { String ad; int adet; long agirlik; }
            static int[] bos() { return new int[3]; }
            static Kayit[] kayitlar() { return new Kayit[3]; }
            static int[] sabitli() { return new int[] {12, 18, 7}; }
            static int uzunluk(int[] d) { return d.length; }
            static int adet(Kayit k) { return k.adet; }
        }
        """;

    public static void main(String[] args) throws Exception {
        System.out.printf("%-10s %6s  %s%n", "yontem", "komut", "kaynakta yazilmayan adim");
        for (Olcek.Yontem y : Olcek.oku(K, "DiziOrnek").yontem())
            if (!y.ad().equals("<init>"))
                System.out.printf("%-10s %6d  %s%n", y.ad(), y.komut(),
                        y.eklenen().isEmpty() ? "-" : String.join(", ", y.eklenen()));

        System.out.println();
        System.out.println("d.length okuma: " + Olcek.komutlar(K, "DiziOrnek", "uzunluk"));
        System.out.println("k.adet okuma:   " + Olcek.komutlar(K, "DiziOrnek", "adet"));

        int[] sayilar = new int[3];
        Kayit[] kayitlar = new Kayit[3];
        System.out.println();
        System.out.println("int[] sinifi:      " + sayilar.getClass().getName());
        System.out.println("Kayit[] sinifi:    " + kayitlar.getClass().getName());
        System.out.println("dizinin ust sinifi: " + sayilar.getClass().getSuperclass().getName());
        System.out.println("baslangic degerleri: " + Arrays.toString(sayilar)
                + " " + Arrays.toString(kayitlar));

        try {
            Olcek.oku(K.replace("return d.length;", "d.length = 5; return 0;"), "DiziOrnek");
        } catch (IllegalStateException e) {
            System.out.println("d.length = 5   -> " + e.getMessage());
        }
    }
}
```

```
yontem      komut  kaynakta yazilmayan adim
bos             3  yeni dizi int
kayitlar        3  yeni dizi DiziOrnek$Kayit
sabitli        15  yeni dizi int
uzunluk         3  -
adet            3  -

d.length okuma: [aload_0, arraylength, ireturn]
k.adet okuma:   [aload_0, getfield, ireturn]

int[] sinifi:      [I
Kayit[] sinifi:    [LKayit;
dizinin ust sinifi: java.lang.Object
baslangic degerleri: [0, 0, 0] [null, null, null]
d.length = 5   -> derlenmedi: DiziOrnek
```

İlk iki satır dizi üretiminin **üç komut** olduğunu söylüyor: boyutu yükle, diziyi üret,
döndür. Ölçek bu üretimi `yeni dizi` diye kaydediyor, çünkü sınıf dosyasında dizi üretimi
nesne üretimiyle aynı sınıfa girer. `Kayit[3]` satırının kaydında sınıfın **tam adı**
duruyor, öğe tipi diziye yazılmıştır.

Üçüncü satır bir fark koyuyor. Köşeli ayraç içinde üç değer yazan `sabitli` yöntemi
**15** komut üretiyor; boyu aynı olan boş dizi **3** komut. Aradaki on iki komut, üç öğenin
tek tek yazılmasıdır: her öğe için diziyi çoğalt, konumu yükle, değeri yükle, yaz. Kaynakta
tek bir sabit gibi duran `{12, 18, 7}` yazımının sınıf dosyasında sabit karşılığı yoktur.
İlk derste ölçülen sabit katlama sayılarda işler; dizide işlemez, çünkü katlanacak şey bir
değer değil, çalışma zamanında üretilen bir nesnedir.

Son üç satır bunu adıyla koyuyor. Dizinin bir sınıfı var — `int[]` için `[I`, `Kayit[]`
için `[LKayit;` — ve o sınıfın üst sınıfı `java.lang.Object`. Dizi bir nesnedir: öbekte
üretilir, bir referansla tutulur, `Object` bekleyen her yere geçer. Üretim öğeleri üretmez;
sayı dizisi sıfırlarla, kayıt dizisi `null` ile başlar. Kayıt dizisi kurmak üç kayıt
kurmaz, üç boş yer kurar.

Uzunluk satırları ayrımın ikincisini veriyor. `d.length` yazımı `arraylength` komutuna,
`k.adet` yazımı `getfield` komutuna derleniyor. Sözdizim ikisinde de aynı — nokta ve bir ad
— ama karşılıkları ayrı komutlardır. `length` bir alan değildir; sınıf dosyasında alan
listesinde bulunmaz, kendi komutu vardır. Bunun görünen sonucu son satırda: `d.length = 5`
yazan kaynak **derlenmiyor**. Bir diziyi büyütmek bir yasak yüzünden değil, karşılığı olan
bir komut bulunmadığı için olanaksızdır.

## Sınırı Denetleyen Adım Kaynakta Yok

- **SD25** — Sınır ölçümünde yalnız istisnanın **sınıf adı** basılır. İstisna iletisi
  konumu ve uzunluğu içerir; o metin basılmaz, çünkü ölçülen şey denetimin varlığıdır.

```java
// Erisim.java — sınır denetimi hangi komutun içinde
public class Erisim {
    static final String K = """
        class ErisimOrnek {
            static int oku(int[] d, int i) { return d[i]; }
            static void yaz(int[] d, int i, int v) { d[i] = v; }
        }
        """;

    public static void main(String[] args) throws Exception {
        System.out.println("d[i] okuma: " + Olcek.komutlar(K, "ErisimOrnek", "oku"));
        System.out.println("d[i] yazma: " + Olcek.komutlar(K, "ErisimOrnek", "yaz"));

        int[] d = {12, 18, 7};
        System.out.println();
        for (int i : new int[] {0, 2, 3, -1}) {
            try {
                System.out.printf("d[%d] -> %d%n", i, d[i]);
            } catch (RuntimeException e) {
                System.out.printf("d[%d] -> %s%n", i, e.getClass().getSimpleName());
            }
        }
        int boy = -1;
        try {
            System.out.println("new int[boy] -> " + new int[boy].length);
        } catch (RuntimeException e) {
            System.out.println("new int[boy] -> " + e.getClass().getSimpleName() + " (boy = " + boy + ")");
        }
    }
}
```

```
d[i] okuma: [aload_0, iload_1, iaload, ireturn]
d[i] yazma: [aload_0, iload_1, iload_2, iastore, return]

d[0] -> 12
d[2] -> 7
d[3] -> ArrayIndexOutOfBoundsException
d[-1] -> ArrayIndexOutOfBoundsException
new int[boy] -> NegativeArraySizeException (boy = -1)
```

Okuma dört, yazma beş komut. İkisinde de bir karşılaştırma, bir dallanma ya da bir çağrı
yok: diziyi yükle, konumu yükle, oku ya da yaz. Sınır denetimi kaynakta yazılmamıştır ve
sınıf dosyasında da **ayrı bir komut olarak durmaz**. Denetim `iaload` ve `iastore`
komutlarının tanımının içindedir; sanal makine her erişimde onu yapar ve konum aralık
dışındaysa istisna fırlatır.

Bu, eklenen adımın üçüncü biçimidir. Birincisi sınıf dosyasına konan bir komuttur —
çevirme, çağrı, üretim. İkincisi kaynakta hiç yazılmamış bir üyedir. Üçüncüsü ise komutun
kendi tanımına gömülüdür ve **komut sayısını hiç değiştirmez**; ölçek onu sayamaz, ancak
çalışma zamanındaki sonucundan okur. Ölçümdeki dört erişimin ikisi değer veriyor, ikisi
istisna; eksi konum ayrı bir kural değil, aynı kuralın sonucudur.

Son satır denetimin ikinci yerini gösteriyor: boyutu eksi olan üretim isteği de çalışma
zamanında düşer ve ayrı bir istisna verir, çünkü boyut derleme zamanında bilinmek zorunda
değildir.

## Çok Boyutlu Dizi Bir Dizi Dizisidir

- **SD26** — Satır uzunlukları ölçümde tek tek yazılır; hiçbiri rastgele üretilmez, hiçbiri
  ortamdan okunmaz.

```java
// CokBoyut.java — çok boyutlu dizi bir dizi dizisidir
public class CokBoyut {
    static final String K = """
        class BoyutOrnek {
            static int[][] duzgun() { return new int[2][3]; }
            static int[][] tirtikli() { return new int[2][]; }
            static int satirUzunlugu(int[][] d, int i) { return d[i].length; }
        }
        """;

    public static void main(String[] args) throws Exception {
        for (String y : new String[] {"duzgun", "tirtikli", "satirUzunlugu"})
            System.out.printf("%-14s %s%n", y, Olcek.komutlar(K, "BoyutOrnek", y));

        int[][] t = new int[3][];
        t[0] = new int[] {12};
        t[1] = new int[] {18, 7, 4};
        t[2] = new int[0];
        System.out.println();
        System.out.println("dis dizinin sinifi: " + t.getClass().getName());
        System.out.println("bir satirin sinifi: " + t[0].getClass().getName());
        System.out.printf("dis uzunluk %d, satir uzunluklari %d %d %d%n",
                t.length, t[0].length, t[1].length, t[2].length);

        int[][] d = new int[2][3];
        System.out.println("duzgun dizide satirlar ayni nesne mi: " + (d[0] == d[1]));
        d[0][0] = 12;
        System.out.println("d[0][0] = 12 sonrasi d[1][0]: " + d[1][0]);
    }
}
```

```
duzgun         [iconst_2, iconst_3, multianewarray, areturn]
tirtikli       [iconst_2, anewarray, areturn]
satirUzunlugu  [aload_0, iload_1, aaload, arraylength, ireturn]

dis dizinin sinifi: [[I
bir satirin sinifi: [I
dis uzunluk 3, satir uzunluklari 1 3 0
duzgun dizide satirlar ayni nesne mi: false
d[0][0] = 12 sonrasi d[1][0]: 0
```

Üçüncü satır dersin cümlesini yazıyor: `d[i].length` okuması **iki** adımdır. Önce `aaload`
ile satır yüklenir — çünkü satır bir referanstır, bir nesnedir — sonra o nesnenin uzunluğu
`arraylength` ile okunur. İki boyutlu dizi tek bir bitişik blok değildir; dış dizinin
öğeleri iç dizilere giden referanslardır. Sınıf adı da bunu yazıyor: dış dizinin sınıfı
`[[I`, bir satırınki `[I`.

İlk iki satır iki ayrı üretimi ayırıyor. Bütün boyutları verilen `new int[2][3]` tek bir
`multianewarray` komutudur ve dış diziyle birlikte satırları da üretir. Yalnız dış boyutu
verilen `new int[2][]` ise `anewarray` komutudur; dış dizi üretilir, satırları `null`
kalır. İkincisi satırların **ayrı uzunlukta** kurulmasına izin verir: ölçümdeki üç satırın
uzunlukları 1, 3 ve 0. Son iki satır ise düzgün dizide bile satırların ayrı nesneler
olduğunu doğruluyor — `d[0]` ile `d[1]` aynı nesne değil, ve birinci satıra yazmak ikinciyi
değiştirmiyor. Java'da ayrı bir çok boyutlu dizi tipi yoktur.

## Yazma Başına Bir Tip Denetimi

- **SD27** — Aynı yazma üç ayrı kaynakta denenir. İkisi derlenir ve komutları basılır,
  biri derlenmez ve "derlenmedi" satırıyla geçer; hangisinin hangi zamanda düştüğü
  ölçümün kendisidir.

```java
// Kovaryans.java — dizi kovaryansı: derlenen yazma, düşen yazma
public class Kovaryans {
    static final String DIZGI = "class KovOrnek { static void yaz(String[] d) { d[0] = %s; } }";
    static final String NESNE = "class KovOrnek { static void yaz(Object[] d) { d[0] = %s; } }";

    static void dene(String ad, String kaynak) {
        try {
            System.out.printf("%-28s -> %s%n", ad, Olcek.komutlar(kaynak, "KovOrnek", "yaz"));
        } catch (Exception e) {
            System.out.printf("%-28s -> %s%n", ad, e.getMessage());
        }
    }

    public static void main(String[] args) throws Exception {
        dene("String[] d; d[0] = \"kuzey\"", DIZGI.formatted("\"kuzey\""));
        dene("String[] d; d[0] = 12", DIZGI.formatted("12"));
        dene("Object[] d; d[0] = 12", NESNE.formatted("12"));

        String[] adlar = new String[2];
        Object[] gorunum = adlar;
        System.out.println();
        System.out.println("Object[] gorunum = adlar;  ayni nesne mi: " + (gorunum == adlar));
        System.out.println("gorunum sinifi: " + gorunum.getClass().getName());
        gorunum[0] = "kuzey";
        System.out.println("gorunum[0] = \"kuzey\" -> adlar[0] = " + adlar[0]);
        try {
            gorunum[1] = 12;
            System.out.println("gorunum[1] = 12 -> " + adlar[1]);
        } catch (RuntimeException e) {
            System.out.println("gorunum[1] = 12 -> " + e.getClass().getSimpleName()
                    + ", adlar[1] = " + adlar[1]);
        }
        int[] sayilar = new int[2];
        sayilar[1] = 12;
        System.out.println("int[] tarafinda ayni yazma -> " + sayilar[1]);
    }
}
```

```
String[] d; d[0] = "kuzey"   -> [aload_0, iconst_0, ldc, aastore, return]
String[] d; d[0] = 12        -> derlenmedi: KovOrnek
Object[] d; d[0] = 12        -> [aload_0, iconst_0, bipush, invokestatic, aastore, return]

Object[] gorunum = adlar;  ayni nesne mi: true
gorunum sinifi: [Ljava.lang.String;
gorunum[0] = "kuzey" -> adlar[0] = kuzey
gorunum[1] = 12 -> ArrayStoreException, adlar[1] = null
int[] tarafinda ayni yazma -> 12
```

Java'da diziler **kovaryanttır** (array covariance): öğe tipi bir üst tipin altındaysa,
dizi de o üst tipin dizisi yerine geçer. `String[]` bir `Object[]` yerine geçer, ve
ölçümün dördüncü satırı bunu doğruluyor — iki ad aynı nesneyi tutuyor, sınıfı hâlâ
`[Ljava.lang.String;`.

İlk üç satır kovaryansın bedelini yazıyor. `String[]` olarak adlandırılan diziye sayı
yazan kaynak **derlenmiyor**: derleyici bildirilen tipe bakar ve hatayı derleme zamanında
verir. Aynı dizi `Object[]` olarak adlandırıldığında **aynı yazma derleniyor** — üstelik
sayıyı sarmalayıcıya çeviren bir çağrı da eklenerek. Yazma sözdizim düzeyinde geçerlidir,
çünkü `Object[]` içine her nesne yazılabilir.

Kararı çalışma zamanı veriyor: dizgi yazması geçiyor ve çağırana görünüyor, sayı yazması
`ArrayStoreException` ile düşüyor ve `adlar[1]` **hâlâ `null`** — yazma yapılmadı, yarım
da kalmadı. Sanal makine `aastore` komutunu yürütürken değerin dizinin **gerçek** öğe
tipine uyup uymadığını denetler; uymuyorsa yazmaz.

Buradaki sınırlayıcı ölçüm iki yönlüdür. Birincisi: bu denetim komut sayısına hiç
yansımaz. `aastore` tek komuttur ve `iastore` da tek komuttur; sınıf dosyasına bakarak
denetimin varlığını sayamayız. İkincisi: son satırdaki `int[]` yazmasında böyle bir denetim
**yoktur**. Öğe tipi ilkelse dizi kovaryansı diye bir soru doğmaz, çünkü ilkel tipli bir
dizi başka bir dizi tipinin yerine geçmez. Eklenen adım burada kaybolur — ve kaybolduğu
yer, tam olarak alt tip ilişkisinin bittiği yerdir.

## Özet

- Dizi bir nesnedir: kendi sınıfı vardır, üst sınıfı `java.lang.Object`'tir ve üretimi
  sınıf dosyasında **3** komuttur; köşeli ayraçlı `{12, 18, 7}` yazımı ise **15** komuttur,
  çünkü öğeler tek tek yazılır. Üretim öğeleri üretmez: sayı dizisi sıfırlarla, referans
  dizisi `null` değerlerle başlar.
- `d.length` bir alan okuması değildir; `arraylength` komutuna derlenir, `k.adet` ise
  `getfield` komutuna. Uzunluğa yazan kaynak derlenmez.
- Sınır denetimi ne kaynakta ne de ayrı bir komutta durur; erişim komutunun tanımının
  içindedir, komut sayısını değiştirmez ve aralık dışı erişimde istisna fırlatır.
- `int[][]` ayrı bir tip değil, bir `int[]` dizisidir: `d[i].length` iki komuttur, satırlar
  ayrı nesnelerdir ve ayrı uzunlukta olabilir.
- Dizi kovaryansı yüzünden `Object[]` olarak adlandırılan bir dizgi dizisine sayı yazmak
  derlenir ama çalışma zamanında `ArrayStoreException` ile düşer; aynı denetim ilkel tipli
  dizide hiç yoktur.

## Sonraki Adım

Bu derste `String[]` dizisine yazmanın çalışma zamanında denetlendiği ölçüldü; yazılan
değer her seferinde hazır bir dizgi nesnesiydi. Sıradaki ders o nesneye bakar: bir dizgi
sabiti sınıf dosyasında nerede durur, aynı sabiti iki kez yazmak kaç nesne üretir, ve
döngü içinde birleştirilen bir metin yol boyunca kaç nesne bırakır? Dizginin
değiştirilemez olması da, dizinin sabit boyutlu olması gibi, kaynakta görünmeyen adımları
belirler.
