İç Sınıflar (Inner Classes)
Java'da bir sınıfın içine başka bir sınıf yerleştirebilirsin. Bu iç sınıflar (nested classes), yalnızca bir yerde kullanılan yardımcı yapıları, ait oldukları sınıfın yanında tutmanı sağlar — kod hem düzenli hem de kap…
İç Sınıflar (Inner Classes)
Java'da bir sınıfın içine başka bir sınıf yerleştirebilirsin. Bu iç sınıflar (nested classes), yalnızca bir yerde kullanılan yardımcı yapıları, ait oldukları sınıfın yanında tutmanı sağlar — kod hem düzenli hem de kapsüllenmiş olur. İç sınıfların dört türü vardır; her birinin kendine özgü kuralları ve kullanım yeri vardır.
Dört tür
- Üye (member) iç sınıf —
staticolmayan, dış nesneye bağlı. - Static nested sınıf —
static, dış nesneye bağlı değil. - Yerel (local) sınıf — bir metodun içinde tanımlı.
- Anonim (anonymous) sınıf — isimsiz, anında tanımlanan (ayrı bir konu).
1) Üye iç sınıf
Dış nesnenin bir parçasıdır ve onun (private dahil) üyelerine doğrudan erişir. Her üye iç nesnenin, gizli bir "dış nesne" referansı vardır; bu yüzden oluşturmak için önce bir dış nesne gerekir:
Banka banka = new Banka("Ziraat"); Banka.Hesap hesap = banka.new Hesap(...); // disNesne.new Ic(...)
Örnek 1 (./Ornek1.java): Bir Banka içindeki Hesap iç sınıfı, dış nesnenin private bankaAdi
alanına erişir. Bu tür sınıflar, dış sınıfın iç durumuyla sıkı çalışan yardımcılar (ör. bir
koleksiyonun Iterator'ı) için idealdir.
2) Static nested sınıf
static olduğundan dış nesneye bağlı değildir; doğrudan Dis.StatikIc ile oluşturulur. Dış
sınıfın yalnızca static üyelerine erişebilir. En yaygın kullanımı Builder ve yardımcı veri
yapılarıdır:
Mesaj m = new Mesaj.Builder().kime("...").konu("...").build();
Örnek 2 (./Ornek2.java) bir static nested Builder ve sade bir static nested sınıf gösterir.
İpucu: Bir iç sınıfın dış nesneye ihtiyacı yoksa onu
staticyap. Aksi halde her iç nesne gereksiz yere bir dış-nesne referansı taşır (ve bellek sızıntısına yol açabilir).
3) Yerel (local) sınıf
Bir metodun (veya bloğun) içinde tanımlanır ve yalnızca orada görünür. Metodun effectively final yerel değişkenlerine erişebilir:
void m() { String onek = "[LOG] "; class Loglayici { void log(String s) { System.out.println(onek + s); } } new Loglayici().log("..."); }
Çok dar kapsamlı, tek seferlik yardımcılar içindir. Örnek 2 bunu da gösterir. Pratikte yerel sınıf yerine genelde daha kısa olan lambda veya anonim sınıf tercih edilir.
4) Anonim sınıf
İsmi olmayan, bir arayüzü/abstract sınıfı anında uygulayan iç sınıftır. Tek seferlik uygulamalar için kullanılır ve genelde lambda'ya dönüşür. Bu, kendi başına bir konudur (bir sonraki bölüm).
Ne zaman hangisi?
| Tür | Dış nesne gerekir mi? | Kullanım |
|---|---|---|
| Üye iç sınıf | Evet | Dış durumla sıkı çalışan yardımcı (Iterator) |
| Static nested | Hayır | Builder, yardımcı veri yapısı |
| Yerel sınıf | (metoda göre) | Tek metotta kullanılan dar yardımcı |
| Anonim sınıf | (duruma göre) | Tek seferlik arayüz uygulaması (genelde lambda) |
Özet
İç sınıfların dört türünü öğrendik: dış nesneye bağlı üye iç sınıf (Örnek 1), bağımsız static nested sınıf (Builder; Örnek 2) ve metot-içi yerel sınıf. "Dış nesne gerekmiyorsa static yap" kuralı önemlidir. İç sınıflar, ilgili yardımcı yapıları ait oldukları yerde, kapsüllü tutmanı sağlar. Sırada, iç sınıfların en kısa ve en sık kullanılan biçimi: anonim sınıflar.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: Üye (member) iç sınıf — dış nesnenin parçasıdır, dış alanlara erişir.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 Banka banka = new Banka("Ziraat");
7 // Üye iç sınıf, DIŞ nesneye bağlıdır: önce dış nesne, sonra .new ile iç nesne.
8 Banka.Hesap hesap = banka.new Hesap("Ada", 1000);
9 hesap.bilgiYaz(); // iç sınıf, dış nesnenin alanına (bankaAdi) erişebilir
10 hesap.paraYatir(500);
11 hesap.bilgiYaz();
12
13 System.out.println("""
14
15 --- Üye (member) iç sınıf ---
16 Bir dış nesnenin İÇİNDE, ona bağlı olarak yaşar; dış nesnenin (private dahil) üyelerine erişir.
17 Oluşturma: disNesne.new Ic(...). Her iç nesnenin gizli bir 'dış nesne' referansı vardır.
18 Kullanım: dış sınıfın iç durumuyla sıkı çalışan yardımcı yapılar (ör. iterator).""");
19 }
20}
21
22class Banka {
23 private final String bankaAdi;
24 Banka(String bankaAdi) { this.bankaAdi = bankaAdi; }
25
26 // Üye (non-static) iç sınıf: dış nesneye bağlı.
27 class Hesap {
28 private final String sahip;
29 private double bakiye;
30 Hesap(String sahip, double bakiye) { this.sahip = sahip; this.bakiye = bakiye; }
31
32 void paraYatir(double t) { bakiye += t; }
33
34 void bilgiYaz() {
35 // bankaAdi DIŞ sınıfın private alanı; iç sınıf doğrudan erişebilir.
36 System.out.println(bankaAdi + " | " + sahip + " | bakiye: " + bakiye);
37 }
38 }
39}Ornek2
çalıştırılabilir1// Ornek2: Static nested (statik iç) sınıf ve yerel (local) sınıf.
2// Çalıştırma: java Ornek2.java
3public class Ornek2 {
4
5 public static void main(String[] args) {
6 // Static nested sınıf: DIŞ nesne GEREKMEZ; doğrudan oluşturulur.
7 Dis.StatikIc s = new Dis.StatikIc("statik iç");
8 s.yaz();
9
10 // Builder deseni genelde static nested sınıfla kurulur:
11 Mesaj m = new Mesaj.Builder().kime("ada@site.com").konu("Selam").build();
12 System.out.println(m);
13
14 // Yerel (local) sınıf: bir METODUN içinde tanımlanır, yalnızca orada görünür.
15 System.out.println("\nYerel sınıf:");
16 yerelSinifOrnegi();
17 }
18
19 static void yerelSinifOrnegi() {
20 String onek = "[LOG] "; // yerel sınıf, metodun (effectively final) değişkenlerine erişir
21 class Loglayici {
22 void log(String mesaj) { System.out.println(onek + mesaj); }
23 }
24 Loglayici l = new Loglayici();
25 l.log("yerel sınıf çalıştı");
26 }
27}
28
29class Dis {
30 static class StatikIc { // static nested: dış nesneye bağlı DEĞİL
31 private final String ad;
32 StatikIc(String ad) { this.ad = ad; }
33 void yaz() { System.out.println("StatikIc: " + ad); }
34 }
35}
36
37class Mesaj {
38 private final String kime, konu;
39 private Mesaj(Builder b) { this.kime = b.kime; this.konu = b.konu; }
40 @Override public String toString() { return "Mesaj{kime=" + kime + ", konu=" + konu + "}"; }
41
42 // Static nested Builder — dış sınıfın bir örneğine ihtiyaç duymadan çalışır.
43 static class Builder {
44 private String kime = "", konu = "";
45 Builder kime(String k) { this.kime = k; return this; }
46 Builder konu(String k) { this.konu = k; return this; }
47 Mesaj build() { return new Mesaj(this); }
48 }
49}