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.
staticmetotlarprivatemetotlar (alt sınıftan görünmez)finalmetotlar (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ğlama | Dinamik bağlama | |
|---|---|---|
| Ne zaman | Derleme anında | Çalışma anında |
| Neye göre | Referans tipi | Nesnenin gerçek tipi |
| Kapsam | overload, static, private, final, alanlar | override edilmiş instance metotlar |
| Polimorfik mi | Hayır | Evet |
| Performans | Biraz 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ılabilir1// 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}Ornek2
çalıştırılabilir1// 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}Ornek3
çalıştırılabilir1// 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}