Eğitim Portalı/Java/Statik ve Dinamik Bağlama (Static & Dynamic Binding)
Java01-java/40-statik-vs-dinamik-baglama

Statik ve Dinamik Bağlama (Static & Dynamic Binding)

Bir metot çağrısı yazdığında — nesne.metot() — Java'nın hangi gerçek metodu çalıştıracağına karar vermesi gerekir. Bu karara bağlama (binding) denir ve iki zamanda olabilir: derleme anında (statik/early binding) veya…

Statik ve Dinamik Bağlama (Static & Dynamic Binding)

Bir metot çağrısı yazdığında — nesne.metot() — Java'nın hangi gerçek metodu çalıştıracağına karar vermesi gerekir. Bu karara bağlama (binding) denir ve iki zamanda olabilir: derleme anında (statik/early binding) veya çalışma anında (dinamik/late binding). Bu ayrımı anlamak, polimorfizmin nasıl çalıştığını ve bazı sinsi tuzakları (alan gizleme gibi) kavramak için şarttır — ve teknik mülakatların klasik sorularındandır.

Statik bağlama (derleme anında)

Derleyici, çağrılacak metodu derleme anında, referans tipine bakarak belirler. Şunlar statik bağlanır:

  • Overloaded (aşırı yüklenmiş) metotlar: Hangi sürümün çağrılacağı, argümanın derleme-zamanı tipine göre seçilir.
  • static metotlar
  • private metotlar (alt sınıftan görünmez)
  • final metotlar (ezilemez)
static void yaz(int x) {...}    static void yaz(String x) {...}
yaz(5);      // derleyici int sürümünü seçer (statik)
yaz("beş");  // String sürümü

Örnek 1 (./Ornek1.java) overloading'i ve static metotların referans tipine göre çözüldüğünü gösterir. Bunlar polimorfik değildir; alt sınıf bir static metodu "ezemez", yalnızca gizler (hides).

Dinamik bağlama (çalışma anında)

Override edilmiş (instance) metotlar ise çalışma anında, nesnenin gerçek tipine göre çözülür. Bu, polimorfizmin motorudur: JVM, her nesnenin gerçek sınıfına ait metodu bir "sanal metot tablosu" (vtable) üzerinden bulur.

Sekil s = new Daire(2);   // referans: Sekil, gerçek: Daire
s.alan();                 // Daire.alan() çalışır (gerçek tipe göre — dinamik)

Örnek 2 (./Ornek2.java) üst tiple (Sekil) yazılan kodun her alt tipin (Daire/Kare) kendi alan() davranışını çalıştırdığını gösterir. Bu sayede "üst tiple programla, alt tip davransın" mümkün olur.

Klasik tuzak: alan gizleme (field hiding)

İşte en sık karıştırılan nokta: alanlar polimorfik değildir. Alan erişimi statik bağlanır (referans tipine göre), instance metotlar ise dinamik bağlanır (gerçek tipe göre):

class Ata  { String tip = "ata";  String tipMetot() { return "ata"; } }
class Cocuk extends Ata { String tip = "cocuk"; String tipMetot() { return "cocuk"; } }

Ata ref = new Cocuk();
ref.tip;        // "ata"   <- ALAN: referans tipine göre (statik)
ref.tipMetot(); // "cocuk" <- METOT: gerçek tipe göre (dinamik)

Örnek 3 (./Ornek3.java) bu tuzağı canlı gösterir. Kural: Alanları override etmeye çalışma; davranış için her zaman metot kullan ve alanları private tut (zaten erişim metotlarından geçer, tuzak oluşmaz).

Karşılaştırma

Statik bağlamaDinamik bağlama
Ne zamanDerleme anındaÇalışma anında
Neye göreReferans tipiNesnenin gerçek tipi
Kapsamoverload, static, private, final, alanlaroverride edilmiş instance metotlar
Polimorfik miHayırEvet
PerformansBiraz daha hızlıÇok küçük ek maliyet (vtable)

Özet

İki bağlama türünü öğrendik: derleme-anında, referans-tipine göre statik bağlama (overloading, static/private/final metotlar ve alanlar — Örnek 1) ve çalışma-anında, gerçek-tipe göre dinamik bağlama (override edilmiş instance metotlar — polimorfizm; Örnek 2). Alan gizleme tuzağını (alanlar statik, metotlar dinamik — Örnek 3) gördük. Bu kavram, polimorfizmin "kaputun altında" nasıl çalıştığını açıklar. Sırada, nesne kurulurken kodun hangi sırayla çalıştığı: başlatma blokları.

Kod Örnekleri(3)

Ornek1

çalıştırılabilir
Ornek1.java
1// Ornek1: Statik bağlama (static/early binding) — DERLEME anında çözülür.
2// Overloading, static/private/final metotlar derleme anında, REFERANS tipine göre seçilir.
3// Çalıştırma: java Ornek1.java
4public class Ornek1 {
5
6    // Metot AŞIRI YÜKLEME (overloading): hangi yaz(...) çağrılacağı DERLEME anında, argüman tipine göre.
7    static void yaz(int x)    { System.out.println("int sürümü: " + x); }
8    static void yaz(double x) { System.out.println("double sürümü: " + x); }
9    static void yaz(String x) { System.out.println("String sürümü: " + x); }
10
11    public static void main(String[] args) {
12        // Derleyici, argümanın STATİK (derleme-zamanı) tipine bakarak sürümü seçer.
13        yaz(5);        // int
14        yaz(5.0);      // double
15        yaz("beş");    // String
16
17        // static metotlar da REFERANS tipine göre çözülür (statik bağlama):
18        Ata a = new Cocuk();
19        a.statikMetot();   // "Ata.statikMetot" — referans tipi Ata olduğu için (DİNAMİK değil!)
20
21        System.out.println("""
22
23                --- Statik bağlama (early binding) ---
24                Çağrılacak metot DERLEME anında, REFERANS tipine göre belirlenir. Şunlar statik bağlanır:
25                  - overloaded metotlar (argüman tipine göre seçim),
26                  - static metotlar,
27                  - private metotlar,
28                  - final metotlar.
29                Bunlar polimorfik DEĞİLDİR; alt sınıf 'ezemez' (override değil, gizleme/farklı metot).""");
30    }
31}
32
33class Ata {
34    static void statikMetot() { System.out.println("Ata.statikMetot"); }
35}
36class Cocuk extends Ata {
37    static void statikMetot() { System.out.println("Cocuk.statikMetot"); } // gizleme (hiding), override değil
38}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek2

çalıştırılabilir
Ornek2.java
1// Ornek2: Dinamik bağlama (dynamic/late binding) — ÇALIŞMA anında çözülür.
2// Override edilmiş (instance) metotlar, nesnenin GERÇEK tipine göre çağrılır (polimorfizm).
3// Çalıştırma: java Ornek2.java
4import java.util.List;
5
6public class Ornek2 {
7
8    public static void main(String[] args) {
9        // Referans tipi Sekil olsa da, ÇAĞRILAN metot nesnenin GERÇEK tipine göre seçilir.
10        List<Sekil> sekiller = List.of(new Daire(2), new Kare(3), new Daire(1));
11        for (Sekil s : sekiller) {
12            // s.alan() -> Daire mi Kare mi olduğuna ÇALIŞMA anında karar verilir (dinamik bağlama).
13            System.out.printf("%-6s alan = %.2f%n", s.ad(), s.alan());
14        }
15
16        Sekil s = new Daire(5);
17        s = new Kare(4);             // referans aynı, gerçek tip değişti
18        System.out.println("\nSon nesnenin alanı: " + s.alan() + " (Kare — gerçek tipe göre)");
19
20        System.out.println("""
21
22                --- Dinamik bağlama (late binding) ---
23                Override edilmiş instance metotlar, REFERANS tipine değil NESNENİN GERÇEK tipine göre çağrılır.
24                Karar ÇALIŞMA anında verilir (sanal metot tablosu / vtable). Polimorfizmin motorudur.
25                Bu sayede üst tiple (Sekil) yazılan kod, her alt tipin kendi davranışını çalıştırır.""");
26    }
27}
28
29abstract class Sekil {
30    abstract double alan();      // override edilecek -> dinamik bağlanır
31    abstract String ad();
32}
33class Daire extends Sekil {
34    private final double r; Daire(double r) { this.r = r; }
35    @Override double alan() { return Math.PI * r * r; }
36    @Override String ad() { return "Daire"; }
37}
38class Kare extends Sekil {
39    private final double k; Kare(double k) { this.k = k; }
40    @Override double alan() { return k * k; }
41    @Override String ad() { return "Kare"; }
42}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek3

çalıştırılabilir
Ornek3.java
1// Ornek3: Klasik tuzak — alanlar STATİK, instance metotlar DİNAMİK bağlanır.
2// Çalıştırma: java Ornek3.java
3public class Ornek3 {
4
5    public static void main(String[] args) {
6        Ata ref = new Cocuk();   // referans tipi: Ata, gerçek tip: Cocuk
7
8        // ALAN: statik bağlanır -> REFERANS tipine (Ata) göre. Tuzak burada!
9        System.out.println("ref.tip (alan)    : " + ref.tip);        // "ata" (Ata.tip)
10
11        // INSTANCE METOT: dinamik bağlanır -> GERÇEK tipe (Cocuk) göre.
12        System.out.println("ref.tipMetot()    : " + ref.tipMetot()); // "cocuk" (Cocuk.tipMetot)
13
14        // Gerçek tiple erişince alan da Cocuk'unkini verir:
15        Cocuk c = new Cocuk();
16        System.out.println("c.tip (alan)      : " + c.tip);          // "cocuk"
17
18        System.out.println("""
19
20                --- Alan gizleme (field hiding) tuzağı ---
21                Alanlar POLİMORFİK DEĞİLDİR; erişim REFERANS tipine göre çözülür (statik bağlama).
22                Instance metotlar ise POLİMORFİKTİR; nesnenin GERÇEK tipine göre çözülür (dinamik bağlama).
23                Bu yüzden 'ref.tip' Ata'nınkini, 'ref.tipMetot()' Cocuk'unkini verir — sık karşılaşılan tuzak.
24                KURAL: alanları override etmeye çalışma; davranış için metot kullan. Alanları private tut.""");
25    }
26}
27
28class Ata {
29    String tip = "ata";                 // alt sınıfta "gizlenecek" (hide), override değil
30    String tipMetot() { return "ata"; } // override edilecek -> dinamik
31}
32class Cocuk extends Ata {
33    String tip = "cocuk";               // ATA.tip'i GİZLER (ayrı bir alan)
34    @Override String tipMetot() { return "cocuk"; }
35}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.