---
title: 'Değişkenler ve Kapsam'
source: 'https://academia.sh/tr/kurslar/java-temelleri/degiskenler-ve-kapsam'
course: 'Java Temelleri'
language: tr
updated: '2026-08-17T18:09:40+00:00'
license: 'CC BY-SA 4.0'
---

# Değişkenler ve Kapsam

Aynı `int adet` bildirimi bulunduğu yere göre üç ayrı şeye derlenir: sınıf gövdesinde bir alana, yöntem gövdesinde bir yuvaya, statik olarak sınıfın tek kopyalı alanına; iki kardeş blokta aynı adı kullanan yöntem, aynı 20 komutu bir eksik yuvayla üretir.

Önceki ders bir değerin hangi biçimde tutulduğunu ölçtü: sayının kendisi mi, yoksa sayıyı
saran bir nesne mi. Fark kaynakta tek harfti, sınıf dosyasında bir çağrıydı. Bu ders aynı
soruyu adın kendisine sorar. `int adet = 5` satırı, yazıldığı yere göre üç ayrı şeye
derlenir; kaynakta üçünün de yazımı **aynıdır**.

Programlama Temelleri kursu değişkeni, bağlamayı, kapsamı ve yaşam süresini kavram olarak
kurmuştu — **bunlar tekrarlanmaz**. Orada bir adın nerede görünür olduğu anlatıldı. Burada
ölçülen şey, derleyicinin o ada sınıf dosyasında **hangi yeri** verdiğidir: sınıfın
gövdesinde duran bir alan mı, yoksa yöntemin çağrı başına ayrılan yerel alanında bir yuva
mı.

## Üç Ad Ailesi

Java bir adı üç yerden birine yazar ve seçimi **bildirimin bulunduğu yer** belirler.

- **Yerel değişken** bir yöntemin gövdesinde bildirilir. Sınıf dosyasında ad olarak
  görünmez; yöntemin yerel alanında numaralı bir **yuva** tutar. Yöntem her çağrıldığında
  yeni bir kopyası oluşur ve çağrı bittiğinde kaybolur. Parametreler de yerel değişkendir.
- **Örnek değişkeni** sınıfın gövdesinde, `static` olmadan bildirilir. Sınıf dosyasında bir
  **alan** olarak durur ve her nesnede ayrı bir kopyası bulunur.
- **Sınıf değişkeni** sınıfın gövdesinde `static` ile bildirilir. O da bir alandır, ama
  kopyası **tektir**: nesne sayısından bağımsız olarak sınıfa aittir.

Ayrım kaynakta bir anahtar sözcüğe ve bir girintiye bağlıdır; sınıf dosyasında ise iki ayrı
yapıya. Alanlar sınıf dosyasının alan çizelgesinde adlarıyla durur. Yerel değişkenler
orada hiç yoktur — yöntemin kodu adları değil, **numaraları** kullanır. Bu ders üç ailenin
ayrımını, kurs boyunca sürdürülen depo kaydının `adet` alanı üzerinde ölçer.

## Ölçüm Çekirdeği

Çekirdek önceki dersin çekirdeğidir, iki ölçüm eklenmiştir: her yöntemin kullandığı
**yuva sayısı** ve o yöntemdeki **alan erişimleri**. Sınıfın alan çizelgesi de okunur.
Derleme başarısızsa sınıf dosyası üretilmez ve çekirdek bunu ayrıca bildirir.

- **SD6** — Yuva sayısı, sınıf dosyasının o yöntem için ayırdığı yerel alan
  büyüklüğüdür — kaynakta yazılan ad sayısı değil. Örnek yöntemlerinde **sıfır numaralı
  yuva `this`'e** ayrılmıştır; statik yöntemlerde ilk parametreden başlar.
- **SD7** — Alan erişimi sütunu komut adını taşır: `getfield` ve `putfield` bir örneğin
  alanına, `getstatic` ve `putstatic` sınıfın alanına erişir.

```java
// Olcek.java — adın sınıf dosyasında nereye yazıldığını okur: alana mı, yuvaya mı
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.classfile.*;
import java.lang.classfile.attribute.CodeAttribute;
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, int yuva, List<String> alanErisimi) {}
    record Sinif(List<String> alan, List<Yontem> yontem) {}

    static Path derle(String kaynak, String sinif) throws Exception {
        Path d = Files.createTempDirectory("olcek");
        Files.writeString(d.resolve(sinif + ".java"), kaynak);
        PrintWriter bos = new PrintWriter(Writer.nullWriter());
        int sonuc = ToolProvider.findFirst("javac").orElseThrow()
                .run(bos, bos, "-d", d.toString(), d.resolve(sinif + ".java").toString());
        return sonuc == 0 ? d.resolve(sinif + ".class") : null;
    }

    static Sinif oku(String kaynak, String sinif) throws Exception {
        Path c = derle(kaynak, sinif);
        if (c == null) throw new IllegalStateException("derlenmedi: " + sinif);
        ClassModel cm = ClassFile.of().parse(c);
        List<String> alanlar = new ArrayList<>();
        for (FieldModel f : cm.fields()) alanlar.add(f.fieldName().stringValue());
        List<Yontem> yontemler = new ArrayList<>();
        for (MethodModel m : cm.methods()) {
            if (m.code().isEmpty()) continue;
            CodeAttribute kod = (CodeAttribute) m.code().get();
            List<String> erisim = new ArrayList<>();
            int komut = 0;
            for (CodeElement e : kod) {
                if (e instanceof Instruction) komut++;
                if (e instanceof FieldInstruction fi)
                    erisim.add(fi.opcode().name().toLowerCase(Locale.ROOT)
                            + " " + fi.name().stringValue());
            }
            yontemler.add(new Yontem(m.methodName().stringValue(), komut,
                    kod.maxLocals(), erisim));
        }
        return new Sinif(alanlar, yontemler);
    }
}
```

## Dört Ad, Üç Ayrı Yer

Ölçülen sınıf `toplamAdet` ve `adet` adlarını sınıf gövdesinde, `gelen`, `yeni`, `n`, `t`,
`gecici` ve `ikinci` adlarını yöntem gövdelerinde bildirir. `blokKapsami` ile `bloksuz`
**aynı işi aynı sırayla** yapar; aralarındaki tek fark, iki geçici adın küme parantezi
içinde açılıp açılmadığıdır.

```java
// Yer.java — dört ad, üç ayrı yer
public class Yer {
    static final String KAYNAK = """
        class Depo {
            static int toplamAdet = 0;
            int adet;
            void ekle(int gelen) {
                int yeni = adet + gelen;
                adet = yeni;
                toplamAdet += gelen;
            }
            static int blokKapsami(int n) {
                int t = 0;
                { int gecici = n * 2; t += gecici; }
                { int ikinci = n * 3; t += ikinci; }
                return t;
            }
            static int bloksuz(int n) {
                int t = 0;
                int gecici = n * 2; t += gecici;
                int ikinci = n * 3; t += ikinci;
                return t;
            }
            static long genis(long agirlik, int ek) {
                long yeni = agirlik + ek;
                return yeni;
            }
            int gorunen(int adet) { return adet; }
            int alanaErisen(int adet) { return this.adet; }
        }
        """;

    public static void main(String[] args) throws Exception {
        Olcek.Sinif s = Olcek.oku(KAYNAK, "Depo");
        System.out.println("sinif dosyasindaki alanlar: " + s.alan());
        System.out.printf("%-14s %6s %5s  %s%n", "yontem", "komut", "yuva", "alan erisimi");
        for (Olcek.Yontem y : s.yontem())
            System.out.printf("%-14s %6d %5d  %s%n", y.ad(), y.komut(), y.yuva(),
                    y.alanErisimi().isEmpty() ? "-" : String.join(", ", y.alanErisimi()));
    }
}
```

```
sinif dosyasindaki alanlar: [toplamAdet, adet]
yontem          komut  yuva  alan erisimi
<init>              3     1  -
ekle               13     3  getfield adet, putfield adet, getstatic toplamAdet, putstatic toplamAdet
blokKapsami        20     3  -
bloksuz            20     4  -
genis               7     5  -
gorunen             2     2  -
alanaErisen         3     2  getfield adet
<clinit>            3     0  putstatic toplamAdet
```

Alan çizelgesinde **iki** ad var: `toplamAdet` ve `adet`. Kaynakta bildirilen sekiz addan
yalnız ikisi sınıf dosyasında ad olarak duruyor. Kalan altısı hiçbir yerde ad değil;
yalnız yuva numarası olarak yaşıyorlar. Bir yerel değişkenin adı, sınıf dosyasına
**girmez** — derleyicinin işi bittiğinde ad tükenmiştir. Derleyiciye ayrıca söylenirse
adlar hata ayıklama bilgisi olarak sınıf dosyasına eklenebilir, ama bu kodun bir parçası
değildir: yöntemin komutları o bilgi olmadan da aynı yuvaları kullanır. Alan adları ise
seçime bağlı değildir, çünkü onlara sınıfın dışından erişilir ve erişen kod adı bilmek
zorundadır.

`ekle` satırı üç aileyi bir arada gösteriyor. Aynı yöntemde `adet` iki kez örnek alanı
komutuyla (`getfield`, `putfield`), `toplamAdet` iki kez sınıf alanı komutuyla
(`getstatic`, `putstatic`) geçiyor; `gelen` ve `yeni` ise hiçbir alan komutuna girmiyor,
çünkü onlar yuvada. Üç yuva sayılıyor: sıfır `this`, bir `gelen`, iki `yeni`.

Ölçümün asıl satırı ortadaki çifttir. `blokKapsami` ile `bloksuz` **aynı 20 komutu**
üretiyor — çalışma zamanında yapılan iş birebir aynı. Yuva sayısı ayrı: **3** ve **4**.
Küme parantezi çalışma zamanında hiçbir şey yapmaz; yaptığı iş derleme zamanında biter.
Derleyici `gecici` adının ilk bloğun sonunda öldüğünü bildiği için `ikinci` adına **aynı
yuvayı** verir. Blok kapsamı, çalışma zamanında var olmayan bir kavramdır: sınıf
dosyasında ondan geriye kalan tek şey **bir eksik yuvadır**.

`genis` satırı yuvanın ad sayısı olmadığını başka bir yönden gösteriyor: üç ad bildiriliyor,
**beş** yuva sayılıyor. Bir yuva sabit genişliktedir ve 64 bitlik değerler ona sığmaz;
`long agirlik` iki yuva, `int ek` bir yuva, `long yeni` yine iki yuva tutuyor. Yerel alanın
büyüklüğü kaç ad yazıldığına değil, o adların **hangi tipte** olduğuna bağlıdır — önceki
dersin tablosundaki genişlik sütununun sınıf dosyasındaki karşılığı budur.

Son iki satır gölgelemeyi ayırıyor. `gorunen` ile `alanaErisen` aynı imzayı taşıyor ve
ikisinde de `adet` adı geçiyor; biri **hiç** alan erişimi yapmıyor, diğeri `getfield`
ediyor. Parametre olarak bildirilen `adet`, alan olan `adet`'i **gölgeliyor**; alana
ulaşmanın tek yolu `this.adet` yazmak. Hangisinin okunacağı derleme zamanında belirlenir
ve sınıf dosyasında iki ayrı komut olarak durur.

Tablonun iki köşesi de anlamlıdır. `<init>` ve `<clinit>` kaynakta yazılmamış yöntemlerdir;
ilki `adet` alanını hazırlayan yapıcı, ikincisi `toplamAdet = 0` atamasını taşıyan sınıf
başlatma bloğudur. İkisi de önceki konuda ölçülmüştü. `<clinit>`'in yuva sayısının **sıfır**
olması burada anlamlıdır: sınıf başlatma bloğunda `this` yoktur, çünkü ortada henüz hiçbir
nesne yoktur.

## Kapsamın Görünen Sonucu

Yer ayrımının sayı olarak değil, **değer olarak** görünen sonucu vardır. Aynı sınıftan iki
nesne üretildiğinde örnek değişkeni ikiye ayrılır, sınıf değişkeni ayrılmaz.

- **SD8** — İki nesne üretilir ve üçüncü çağrı ikinci nesneye yapılır; sınıf değişkeni
  bütün çağrıların toplamını taşıdığı için beklenen değer 3 artı 4 artı 10'dur.
- **SD9** — Gölgeleme sınaması, alanı önceki çağrıların değiştirdiği bir noktada yapılır;
  böylece parametrenin mi yoksa alanın mı okunduğu değerden ayırt edilebilir.

```java
// Kapsam.java — alanın ve yuvanın görünen sonucu
public class Kapsam {
    static class Depo {
        static int toplamAdet = 0;                 // sinif degiskeni: tek kopya
        int adet;                                  // ornek degiskeni: ornek basina kopya

        void ekle(int gelen) {
            int yeni = adet + gelen;               // yerel degisken: cagri basina kopya
            adet = yeni;
            toplamAdet += gelen;
        }

        int gorunen(int adet) { return adet; }     // parametre alani golgeler
        int alanaErisen(int adet) { return this.adet; }
    }

    public static void main(String[] args) {
        Depo vida = new Depo(), civata = new Depo();
        vida.ekle(3);
        vida.ekle(4);
        civata.ekle(10);
        System.out.println("vida.adet: " + vida.adet + " | civata.adet: " + civata.adet
                + " | Depo.toplamAdet: " + Depo.toplamAdet);
        System.out.println("gorunen(9): " + vida.gorunen(9)
                + " | alanaErisen(9): " + vida.alanaErisen(9));
    }
}
```

```
vida.adet: 7 | civata.adet: 10 | Depo.toplamAdet: 17
gorunen(9): 9 | alanaErisen(9): 7
```

`adet` her nesnede ayrı: **7** ve **10**. `toplamAdet` tek: **17**, yani üç çağrının
toplamı. `yeni` hiçbir yerde görünmüyor, çünkü her çağrının sonunda yok oluyor. Üç ailenin
yaşam süresi de böylece ayrılıyor — yuva çağrı boyunca, örnek alanı nesne boyunca, sınıf
alanı sınıf yüklü kaldığı sürece yaşar.

İkinci satır gölgelemenin bedelini gösteriyor. Aynı nesneye aynı argümanla yapılan iki
çağrı **9** ve **7** döndürüyor. Kaynakta iki yöntemin gövdesi arasında `this.` dışında
hiçbir fark yoktur. Bir alan adıyla aynı adı taşıyan bir parametre, o alanı yöntemin
tamamında erişilemez kılar; okunan şey artık nesnenin durumu değil, çağırandan gelen
argümandır.

## Sınırlayıcı Ölçüm: Hangi Yeniden Bildirim Geçiyor

Gölgeleme her yerde olmaz. İç içe bloklarda aynı adı yeniden bildirmek Java'da **derleme
hatasıdır**; gölgeleme yalnız ayrı ailelerden iki ad arasında, yani alan ile yerel arasında
olur. Aşağıdaki beş biçim aynı sınıf iskeletine yerleştirilir ve yalnız derlenip
derlenmediklerine bakılır.

- **SD10** — Beş durum aynı gövdeye, aynı sınıf adıyla yazılır; ölçüm derleyicinin ürettiği
  metne değil, **sınıf dosyasının oluşup oluşmadığına** bakar. Derleyici iletisi basılmaz.

```java
// Bildirim.java — hangi yeniden bildirim derleme aşamasını geçiyor
public class Bildirim {
    static final String[][] DURUM = {
        {"iki kardes blokta ayni ad",
         "int t = 0; { int g = n; t += g; } { int g = n; t += g; } return t;"},
        {"ic blokta distaki adi yeniden",
         "int t = 0; { int t = n; } return t;"},
        {"ic bloktaki ada disaridan erisim",
         "int t = 0; { int g = n; } return t + g;"},
        {"alan adiyla ayni yerel ad",
         "int adet = n; return adet + this.adet;"},
        {"parametre adiyla ayni yerel ad",
         "int n = 1; return n;"},
    };

    public static void main(String[] args) throws Exception {
        System.out.printf("%-34s %s%n", "bildirim bicimi", "derleme");
        for (String[] d : DURUM) {
            String kaynak = "class D { int adet = 5; int olc(int n) { " + d[1] + " } }";
            System.out.printf("%-34s %s%n", d[0],
                    Olcek.derle(kaynak, "D") != null ? "gecti" : "hata");
        }
    }
}
```

```
bildirim bicimi                    derleme
iki kardes blokta ayni ad          gecti
ic blokta distaki adi yeniden      hata
ic bloktaki ada disaridan erisim   hata
alan adiyla ayni yerel ad          gecti
parametre adiyla ayni yerel ad     hata
```

İki geçen satırın ortak yanı var: ikisinde de **iki ad hiçbir noktada aynı anda görünür
değil**. Kardeş bloklardaki `g` adları birbirini görmez, çünkü birincisi ikincisi
açılmadan kapanmıştır — bu, yuva paylaşımının kaynaktaki karşılığıdır. Alan ile yerel ise
ayrı ailelerdendir ve derleyici hangisinin kastedildiğini `this.` ile ayırabilir.

Üç hatanın ortak yanı da var: hepsinde tek bir yerel ad iki kez bildirilmiş ya da
kapsamı dışında kullanılmıştır. Java'da bir yerel değişkenin adı, kapsamı boyunca
**tekrar bildirilemez**; iç blok dıştakini gölgeleyemez. Beşinci satır bunun en dar
halidir — parametre de bir yerel değişkendir, dolayısıyla aynı adı gövdede yeniden
bildirmek hatadır. Sınır böylece net çizilir: gölgeleme yalnız alan ile yerel arasında
vardır, yerel ile yerel arasında yoktur ve derleyici bunu sınıf dosyası üretmeden önce
reddeder.

Bu yasağın bir bedeli olduğunu da yazmak gerekir: iç blokta kısa ve anlamlı bir ad ikinci
kez kullanılamadığı için uzun yöntemlerde adlar birikir. Karşılığında kazanılan şey,
bir adın bir yöntem gövdesinin herhangi bir noktasında **tek bir bildirimi** olmasıdır —
okuyan kişi bir adı gördüğünde hangi bildirime baktığını aramak zorunda kalmaz. Ölçüm bu
kararın çalışma zamanında hiçbir karşılığı olmadığını gösteriyor: geçen iki biçim de
sınıf dosyasında aynı komutları üretiyor.

## Özet

- Bildirimin yeri adın sınıf dosyasındaki yerini belirler: sınıf gövdesindeki adlar
  **alan** çizelgesine girer, yöntem gövdesindekiler yalnız numaralı bir **yuva** tutar
  ve sınıf dosyasında ad olarak görünmez.
- `ekle` yöntemi üç aileyi bir arada gösterir: `adet` için `getfield`/`putfield`,
  `toplamAdet` için `getstatic`/`putstatic`, `gelen` ve `yeni` için hiçbir alan komutu.
- Blok kapsamı derleme zamanında biter: `blokKapsami` ile `bloksuz` **aynı 20 komutu**
  üretir, blokluk biçim yalnız **bir yuva** az kullanır.
- Örnek değişkeni nesne başına, sınıf değişkeni sınıf başına, yerel değişken çağrı başına
  yaşar; ölçümde **7**, **10** ve **17** değerleri bu üç ömrü ayırır.
- Gölgeleme yalnız alan ile yerel arasında olur ve `this.` ile çözülür; iç blokta bir
  yerel adı yeniden bildirmek derleme hatasıdır.

## Sonraki Adım

Bu ders adın nereye yazıldığını ölçtü. Adların taşıdığı değerler bir kez yerlerine
oturduğunda sıra onları birleştiren işleçlere gelir. Sıradaki ders `+` ve `+=` gibi tek
karakterlik yazımların sınıf dosyasında ne bıraktığını sayar: `int` ile `long`
toplandığında derleyicinin araya koyduğu çevirme, `+=` yazımının kaynakta hiç yazılmayan
bir daraltmayı kendiliğinden eklemesi ve bunun **görünen** sonucu, kısa devre
değerlendirmenin bir dal komutu olarak sınıf dosyasında belirmesi — ve iki sabitin
toplandığı yerde hiçbir adımın eklenmemesi.
