---
title: 'Erişim Belirteçleri'
source: 'https://academia.sh/tr/kurslar/java-nesne-modeli/erisim-belirtecleri'
course: 'Nesneye Dayalı Java'
language: tr
updated: '2026-08-17T18:09:40+00:00'
license: 'CC BY-SA 4.0'
---

# Erişim Belirteçleri

Dört görünürlük düzeyi ile dört çağrı konumu çaprazlandığında on altı çiftin onu derlenir; kararın tamamı derleme zamanında verilir ve çalışma zamanında üye yerinde durur — sınıf dosyasında dört alanın dördü de vardır, ayrımı yalnız bir bayrak taşır. Korumalı düzey paket içini de açar.

Önceki ders bir nesnenin kuruluş anını ölçtü ve sonunda beklenmedik bir yerden bir belirteç
çıktı: `private` yazılan yöntem alt sınıfa hiç miras kalmadığı için yapıcı tuzağı orada
doğmadı. O tek sözcük bir kararın tarafını değiştirdi, ama sözcüğün kendisi ölçülmedi.

Bu ders onu ölçer. Sorusu şudur: bir üyenin **kimden görüldüğüne** kim karar veriyor, ve bu
karar ne zaman veriliyor? Yanıt bu kursta beklenenden daha kesindir. Görünürlük, kursun
ölçtüğü sekiz kararın en uçtaki örneğidir: kararın tamamı **bildirilen tipe** ve derleme
zamanına aittir, çalışma zamanının hiçbir katkısı yoktur. Ölçüm bunu iki yönden gösterir —
derlenen ve derlenmeyen çiftleri sayarak, sonra üyenin çalışma zamanında nerede durduğuna
bakarak.

## Görünürlük Kimin Sorusu

Java dört görünürlük düzeyi tanır ve üçünün adı vardır: `private`, `protected`, `public`.
Dördüncüsü adsızdır — hiçbir belirteç yazılmadığında geçerli olan düzeydir ve **paket
düzeyi** olarak anılır. Bu adsızlık bir ayrıntı değildir: bir üyeyi belirteçsiz bırakmak bir
seçim yapmamak değil, paket içine açık bırakmayı seçmektir.

Düzeylerin tek başına anlamı yoktur; anlam **erişimin nereden denendiğiyle** birlikte doğar.
Bu yüzden ölçüm bir çaprazlamadır: dört düzeyin her biri dört ayrı konumdan denenir. Konumlar
şunlardır — üyeyi bildiren sınıfın kendi içi, aynı paketteki ilgisiz bir sınıf, başka
paketteki bir alt sınıf, başka paketteki ilgisiz bir sınıf. On altı çift çıkar ve her çift
tek bir soruya indirgenir: bu kaynak derleniyor mu?

Nesneye Dayalı Python ve Tipler kursu kapsüllemeyi **ad düzeyinde bir sözleşme** olarak kurmuştu; orada
görünürlük bir anlaşmaydı ve tekrarlanmaz. Buradaki ayrım yapısaldır: kararı veren dilin
kendi derleyicisidir, ve reddi bir uyarı değil, derlenmemiş bir kaynaktır.

## Ölçüm Çekirdeği

Ölçüm hiçbir programı çalıştırmaz. Her çift için bir kaynak kümesi üretilir, derleyici
program içinden çağrılır ve yalnız çıkış durumu okunur.

- **SN7** — Ölçümün kâhini kurgunun kendisidir: her senaryoda üye tek bir yerde bildirilir ve
  tek bir yerden okunur; derleme başarısızlığının başka bir nedeni yoktur.
- **SN8** — Derleyicinin ürettiği bütün iletiler yutulur; ölçülen tek şey çıkış durumudur.
  Kaynağın neden reddedildiği metinden değil, kurgudan okunur.
- **SN9** — Bütün senaryolarda aynı üye kullanılır: `Ust` sınıfının `etiket` adlı alanı.
  Düzeyler arasında değişen tek şey o alanın belirtecidir.

```java
// Derle.java — kaynak kümesini derler; sonuç yalnız derlendi ya da derlenmedi
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.classfile.*;
import java.lang.reflect.AccessFlag;
import java.nio.file.*;
import java.util.*;
import java.util.spi.ToolProvider;

class Derle {
    static boolean olur(Map<String, String> dosya) throws Exception {
        Path d = Files.createTempDirectory("erisim");
        List<String> arg = new ArrayList<>(List.of("-d", d.resolve("cikti").toString()));
        for (var g : dosya.entrySet()) {
            Path p = d.resolve(g.getKey());
            Files.createDirectories(p.getParent());
            Files.writeString(p, g.getValue());
            arg.add(p.toString());
        }
        PrintWriter bos = new PrintWriter(Writer.nullWriter());
        return ToolProvider.findFirst("javac").orElseThrow()
                .run(bos, bos, arg.toArray(String[]::new)) == 0;
    }

    static List<String> alanBayraklari(String kaynak, String sinif) throws Exception {
        Path d = Files.createTempDirectory("bayrak");
        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);
        List<String> satir = new ArrayList<>();
        for (FieldModel f : ClassFile.of().parse(d.resolve(sinif + ".class")).fields()) {
            var b = f.flags();
            satir.add(f.fieldName().stringValue() + " " + (b.has(AccessFlag.PRIVATE) ? "ACC_PRIVATE"
                    : b.has(AccessFlag.PROTECTED) ? "ACC_PROTECTED"
                    : b.has(AccessFlag.PUBLIC) ? "ACC_PUBLIC" : "(bayrak yok)"));
        }
        return satir;
    }
}
```

## On Altı Çiftin Kaçı Derleniyor

```java
// Erisim.java — dört görünürlük düzeyi × dört çağrı konumu
import java.util.*;

public class Erisim {
    static final String[] DUZEY = { "private", "", "protected", "public" };
    static final String[] DUZEY_ADI = { "private", "(varsayilan)", "protected", "public" };
    static final String BICIM = "%-13s %-11s %-11s %-11s %s%n";

    static String ust(String duzey) {
        return "package depo;\npublic class Ust {\n"
                + "    " + duzey + " String etiket = \"ust alan\";\n"
                + "    public String kendi() { return etiket; }\n}\n";
    }

    static Map<String, String> senaryo(String duzey, int konum) {
        Map<String, String> d = new LinkedHashMap<>();
        d.put("depo/Ust.java", ust(duzey));
        switch (konum) {
            case 1 -> d.put("depo/Komsu.java",
                    "package depo;\nclass Komsu { String oku(Ust u) { return u.etiket; } }\n");
            case 2 -> d.put("dis/AltDis.java", "package dis;\nimport depo.Ust;\n"
                    + "public class AltDis extends Ust { public String oku() { return this.etiket; } }\n");
            case 3 -> d.put("dis/Yabanci.java", "package dis;\nimport depo.Ust;\n"
                    + "class Yabanci { String oku(Ust u) { return u.etiket; } }\n");
            default -> { }
        }
        return d;
    }

    public static void main(String[] args) throws Exception {
        System.out.printf(BICIM, "duzey", "ayni sinif", "ayni paket", "alt sinif", "dis paket");
        int derlenen = 0;
        for (int i = 0; i < DUZEY.length; i++) {
            String[] h = new String[4];
            for (int j = 0; j < 4; j++) {
                boolean ok = Derle.olur(senaryo(DUZEY[i], j));
                h[j] = ok ? "derlendi" : "derlenmedi";
                if (ok) derlenen++;
            }
            System.out.printf(BICIM, DUZEY_ADI[i], h[0], h[1], h[2], h[3]);
        }
        System.out.println("16 ciftin derlenen sayisi: " + derlenen);
    }
}
```

```
duzey         ayni sinif  ayni paket  alt sinif   dis paket
private       derlendi    derlenmedi  derlenmedi  derlenmedi
(varsayilan)  derlendi    derlendi    derlenmedi  derlenmedi
protected     derlendi    derlendi    derlendi    derlenmedi
public        derlendi    derlendi    derlendi    derlendi
16 ciftin derlenen sayisi: 10
```

On altı çiftin **onu** derleniyor, altısı derlenmiyor. Tablonun biçimi bir merdivendir: her
satır bir öncekinin açtıklarını açar ve üzerine bir konum ekler. Düzeyler bu yüzden dört ayrı
kural değil, **iç içe geçmiş dört halkadır**; bir üyeyi bir düzeyden ötekine taşımak yeni bir
kapı açar, hiçbirini kapatmaz.

İlk sütun dört satırda da aynıdır. Bir sınıf kendi üyesini her düzeyde görür; `private` bile
sınıfın kendi içinde hiçbir şey kapatmaz. Görünürlük bir üyeyi sahibinden saklamaz, **çağıran
tarafı** sınırlar.

İlk satır ile ikinci satır arasındaki tek fark bir sözcüğün yokluğudur, ve o yokluk aynı
paketteki bütün sınıfları içeri alır. Belirteçsiz bir alan `Komsu` sınıfından okunabiliyor;
`Komsu`, `Ust` ile hiçbir kalıtım ilişkisi taşımıyor, yalnız aynı pakette duruyor. Paket bu
tabloda bir düzenleme birimi değil, bir **erişim sınırıdır**.

Son satırın söylediği ise dördüncü sütunun ilk kez dolmasıdır. `public`, üyeyi bildiren
paketin dışına açılan tek düzeydir; kalan üçü şu ya da bu genişlikte pakete bağlıdır.

Bütün bu kararlar tek bir yerde verilir: derleyicide. On altı senaryonun hiçbirinde program
çalıştırılmadı. Altı çift için ortada bir sınıf dosyası bile yoktur — kusur, çalışan bir
programda bir hata olarak değil, **hiç var olmayan bir program** olarak ortaya çıkar. Kursun
ölçtüğü sekiz karar arasında görünürlük, çalışma zamanı tipinin payının sıfır olduğu uçtur.

## Sınırlayıcı Ölçüm: Korumalı Düzey Paketi de Açar

Tabloda bir satır ilk okumaya direniyor. `protected` düzeyi çoğunlukla "yalnız alt sınıflara
açık" diye okunur; oysa üçüncü satırın ikinci sütunu **derlendi** diyor. Alt sınıf olmayan,
yalnız aynı pakette duran bir sınıf korumalı alanı okuyabiliyor.

Bu tek ölçüm bir kuralı sınırlamakla kalmaz, `protected` düzeyinin biçimini de değiştirir.
Ayrıntıyı görmek için aynı korumalı alan beş ayrı yerden denenir.

- **SN10** — Beş denemede de `Ust` sınıfı ve `etiket` alanı birebir aynıdır; değişen tek şey
  erişimi deneyen sınıfın paketi, kalıtım ilişkisi ve kullandığı **referansın bildirilen
  tipidir**.

```java
// Koruma.java — korumalı düzey tam olarak neyi açıyor
import java.util.*;

public class Koruma {
    static final String UST = "package depo;\npublic class Ust {\n"
            + "    protected String etiket = \"ust alan\";\n}\n";
    static final String ONEK = "package dis;\nimport depo.Ust;\n";

    static final String[][] DENEME = {
        { "ayni paket, ilgisiz sinif", "depo/Komsu.java",
          "package depo;\nclass Komsu { String oku(Ust u) { return u.etiket; } }\n" },
        { "dis paket, alt sinif, this uzerinden", "dis/A.java",
          ONEK + "public class A extends Ust { String oku() { return this.etiket; } }\n" },
        { "dis paket, alt sinif, kendi tipi uzerinden", "dis/B.java",
          ONEK + "public class B extends Ust { String oku(B b) { return b.etiket; } }\n" },
        { "dis paket, alt sinif, Ust tipi uzerinden", "dis/C.java",
          ONEK + "public class C extends Ust { String oku(Ust u) { return u.etiket; } }\n" },
        { "dis paket, ilgisiz sinif", "dis/D.java",
          ONEK + "class D { String oku(Ust u) { return u.etiket; } }\n" },
    };

    public static void main(String[] args) throws Exception {
        System.out.printf("%-44s %s%n", "erisim yeri", "sonuc");
        for (String[] d : DENEME) {
            Map<String, String> k = new LinkedHashMap<>();
            k.put("depo/Ust.java", UST);
            k.put(d[1], d[2]);
            System.out.printf("%-44s %s%n", d[0], Derle.olur(k) ? "derlendi" : "derlenmedi");
        }
    }
}
```

```
erisim yeri                                  sonuc
ayni paket, ilgisiz sinif                    derlendi
dis paket, alt sinif, this uzerinden         derlendi
dis paket, alt sinif, kendi tipi uzerinden   derlendi
dis paket, alt sinif, Ust tipi uzerinden     derlenmedi
dis paket, ilgisiz sinif                     derlenmedi
```

Beş denemenin üçü derleniyor. İlk satır sınırlayıcı ölçümün kendisidir: korumalı üye paketin
tamamına açıktır ve bunun için kalıtım gerekmez. "Korumalı, yalnız alt sınıfa açık demektir"
cümlesi ölçümle yanlışlanıyor.

Üçüncü ile dördüncü satır arasındaki fark ise `protected` düzeyinin en kolay gözden kaçan
yanıdır. İki sınıf da `Ust`'un alt sınıfıdır, ikisi de dış pakettedir, ikisi de aynı alanı
okumaya çalışır. Ayrım okumanın hangi referans üzerinden yapıldığındadır: `B` kendi tipinden
bir referans kullanıyor ve derleniyor, `C` bildirilen tipi `Ust` olan bir referans kullanıyor
ve derlenmiyor. Nesne aynı nesne olabilir; karar nesneye değil, **referansın bildirilen
tipine** bakılarak veriliyor.

Bu, dersin başındaki iddianın en keskin biçimidir. Aynı alan, aynı alt sınıf, aynı satır
biçimi — ve iki ayrı sonuç. Farkı yaratan tek şey, derleyicinin o adı çözerken gördüğü tiptir.
Dış paketteki bir alt sınıf korumalı üyeyi **kendi kalıtım hattı üzerinden** kullanabilir,
üst tipin genel bir aracı olarak kullanamaz.

## Üye Nerede Duruyor

Derleme zamanında reddedilen erişimlerin çalışma zamanında bir karşılığı var mı? Soru,
üyenin sınıf dosyasında ne hâlde durduğuna bakılarak yanıtlanır.

```java
// Bayrak.java — dört düzey sınıf dosyasında ne bırakıyor
public class Bayrak {
    static final String KAYNAK = """
        class Uye {
            private   String gizli   = "";
                      String paket   = "";
            protected String korumali = "";
            public    String acik    = "";
        }
        """;

    public static void main(String[] args) throws Exception {
        var alanlar = Derle.alanBayraklari(KAYNAK, "Uye");
        System.out.println("sinif dosyasindaki alan sayisi: " + alanlar.size());
        for (String s : alanlar) System.out.println("  " + s);
    }
}
```

```
sinif dosyasindaki alan sayisi: 4
  gizli ACC_PRIVATE
  paket (bayrak yok)
  korumali ACC_PROTECTED
  acik ACC_PUBLIC
```

Dört alanın dördü de sınıf dosyasındadır. `private` bildirilen alan silinmemiş, gizlenmemiş,
başka bir yere taşınmamıştır; ötekilerle aynı listede, aynı biçimde durur. Aralarındaki tek
fark bir **bayraktır**.

Paket düzeyinin karşılığı da burada görünür. Öteki üç düzeyin her birinin sınıf dosyasında bir
adı vardır; belirteçsiz alanın hiçbir bayrağı yoktur. Kaynaktaki adsızlık sınıf dosyasında da
adsızdır: paket düzeyi, üç bayrağın hiçbirinin konmamış olmasıdır.

Buradan dersin ikinci yarısı çıkıyor. Görünürlük bir **saklama düzeneği değildir**; üyeyi
kimsenin ulaşamayacağı bir yere koymaz. Yaptığı şey, derleyiciye hangi kaynakları
reddedeceğini söylemektir. Kapsülleme bir engel değil, bir sözleşmedir — ve o sözleşmenin
yaptırımı, çalışan programda değil, hiç doğmayan programda görünür.

## Kusur Kimin Derlemesinde Doğuyor

Bir düzeyi daraltmak, sahibinin kaynağında tek bir sözcük değiştirmektir. Bu değişikliğin
kimi vurduğu ölçülebilir: aynı `Ust` sınıfı iki düzeyle, önce tek başına, sonra dış paketteki
bir çağıranla birlikte derlenir.

```java
// Bedel.java — bir düzey daraltıldığında kusur kimin derlemesinde doğuyor
import java.util.*;

public class Bedel {
    static final String CAGIRAN = "package dis;\nimport depo.Ust;\n"
            + "class Yabanci { String oku(Ust u) { return u.etiket; } }\n";

    static String ust(String duzey) {
        return "package depo;\npublic class Ust {\n    " + duzey
                + " String etiket = \"ust alan\";\n}\n";
    }

    public static void main(String[] args) throws Exception {
        for (String duzey : new String[] { "public", "protected" }) {
            Map<String, String> ikisi = new LinkedHashMap<>();
            ikisi.put("depo/Ust.java", ust(duzey));
            ikisi.put("dis/Yabanci.java", CAGIRAN);
            System.out.printf("%-10s | Ust tek basina: %-9s | cagiranla birlikte: %s%n", duzey,
                    Derle.olur(Map.of("depo/Ust.java", ust(duzey))) ? "derlendi" : "derlenmedi",
                    Derle.olur(ikisi) ? "derlendi" : "derlenmedi");
        }
    }
}
```

```
public     | Ust tek basina: derlendi  | cagiranla birlikte: derlendi
protected  | Ust tek basina: derlendi  | cagiranla birlikte: derlenmedi
```

Orta sütun iki satırda da **derlendi** diyor. `Ust` sınıfının kaynağı korumalı düzeyde de
kusursuzdur; kendi başına derlenir, sınıf dosyası üretilir, hiçbir uyarı çıkmaz. Sahibinin
tarafında görünen bir şey yoktur.

Sağ sütun ise ayrılıyor. Aynı `Yabanci` sınıfı, aynı satır, iki ayrı sonuç — ve `Yabanci`
sınıfının kaynağında hiçbir şey değişmemiştir. Kusur, değişikliği yapan sınıfın derlemesinde
değil, **ona bakan sınıfın derlemesinde** doğuyor.

Bu, kursun her derste sorduğu "bedel nerede görünür" sorusunun buradaki yanıtıdır.
Görünürlüğü genişletmek geriye dönük olarak sorunsuzdur: yeni bir kapı açar, açık olanı
kapatmaz. Daraltmak ise sahibinin göremeyeceği bir yerde kırılma üretir. Bir üyeyi `public`
bildirmenin maliyeti, o üyeyi sonradan geri almanın maliyetidir.

## Özet

- Dört görünürlük düzeyi dört çağrı konumuyla çaprazlandığında on altı çiftin **onu**
  derlenir; tablo iç içe geçmiş dört halka biçimindedir, her düzey bir öncekinin üstüne
  konum ekler.
- Görünürlük üyeyi sahibinden saklamaz — ilk sütun dört düzeyde de derlenir — sınırlanan şey
  **çağıran taraftır**; belirteçsiz düzey de bir seçimsizlik değildir, aynı paketteki ilgisiz
  sınıfları içeri alır ve paketi bir erişim sınırına çevirir.
- Korumalı düzey paket içini de açar: alt sınıf olmayan bir komşu sınıf korumalı alanı okur,
  yani "yalnız alt sınıfa açık" okuması yanlıştır.
- Dış paketteki bir alt sınıf korumalı üyeye **kendi tipinden** bir referansla erişebilir,
  bildirilen tipi üst sınıf olan bir referansla erişemez: karar nesneye değil, referansın
  bildirilen tipine bakar.
- Sınıf dosyasında dört alanın dördü de durur; ayrımı yalnız bir bayrak taşır ve paket
  düzeyinin bayrağı yoktur. Görünürlük saklama değil, derleyiciye verilen bir kuraldır.
- Bir düzey daraltıldığında sahibinin kaynağı yine derlenir; kusur **çağıranın derlemesinde**
  doğar. Genişletmek geriye dönük olarak sorunsuzdur, daraltmak başka bir yerde kırılır.

## Sonraki Adım

İki derstir aynı ikili kullanılıyor ve ikisinde de kararın bir tarafı ölçüldü: yapıcıdan
çağrılan yöntemi çalışma zamanı tipi seçti, erişilebilirliği bildirilen tip belirledi. İkisi
yan yana konmadı. Sıradaki ders bu kursun çekirdek ölçümüdür: tek bir referans üzerinde sekiz
ayrı karar okunur ve kaçının hangi taraftan geldiği sayılır. Aynı satırda `d.ad()` ile
`d.etiket` iki karşıt yanıt verir — alanların aynı adla yeniden bildirilmesi yeniden
tanımlama değil **gizlemedir**, ve gizlenen alan yok olmaz. Aynı derste `@Override` işaretinin
derleme zamanında neyi yakaladığı ve imza değiştiğinde kararın neden taraf değiştirdiği
ölçülür.
