Başlatma Blokları (Initializer Blocks)
Bir nesne new ile oluşturulurken veya bir sınıf ilk kez yüklenirken, alanların belirli değerlerle hazırlanması gerekir. Çoğu zaman bunu constructor'da veya alan tanımında yaparız. Ama Java iki ek araç sunar: örnek baş…
Başlatma Blokları (Initializer Blocks)
Bir nesne new ile oluşturulurken veya bir sınıf ilk kez yüklenirken, alanların belirli
değerlerle hazırlanması gerekir. Çoğu zaman bunu constructor'da veya alan tanımında yaparız. Ama
Java iki ek araç sunar: örnek başlatma bloğu (instance initializer block) ve statik başlatma
bloğu (static initializer block). Bunlar, basit atamalarla yapılamayan başlatma mantığını temiz
bir şekilde toplamayı sağlar. Bu konu aynı zamanda "nesne kurulurken kod hangi sırayla çalışır?"
sorusunu netleştirir.
Instance initializer block
Süslü parantezler içinde, herhangi bir metot dışında yazılan koddur ({ ... }). Her new'de,
constructor gövdesinden önce çalışır:
class Urun { private int x; { x = hesapla(); System.out.println("instance blok"); } // her new'de Urun() { System.out.println("constructor"); } }
Ne işe yarar? Birden çok constructor'ın paylaştığı başlatma kodunu tek yerde toplamak. Üç
farklı constructor'ın hepsinde tekrar edilecek kodu, bir instance bloğa koyarsın; blok hepsinden
önce çalışır. Örnek 1 (./Ornek1.java) bunu ve tam başlatma sırasını gösterir.
Static initializer block
static { ... } bloğu, sınıf ilk yüklendiğinde bir kez çalışır (tüm static alanlardan sonra,
herhangi bir nesne oluşturulmadan veya static metot çağrılmadan önce). Tek satırda atanamayan
karmaşık statik başlatma içindir:
class DovizTablosu { private static final Map<String,Double> KURLAR; static { // bir kez, sınıf yüklenince Map<String,Double> m = new HashMap<>(); m.put("USD", 32.50); m.put("EUR", 35.10); KURLAR = Collections.unmodifiableMap(m); } }
Kullanım: sabit tablolar/haritalar kurmak, yapılandırma/kaynak yüklemek, hesaplanmış sabitler
üretmek. Basit atamalar için gerek yoktur (static int X = 5; yeter). Örnek 2 (./Ornek2.java)
bir döviz tablosunu static blokta kurar.
Tam başlatma sırası
Bir nesne oluşturulurken kod şu sırayla çalışır:
- (Yalnızca ilk kez, sınıf yüklenince) static alan başlatmaları + static bloklar — yazıldıkları sırada, bir kez.
- Her
new'de:- Önce üst sınıf kurulur (
super(...)). - Sonra instance alan başlatmaları + instance initializer blokları, kodda yazıldıkları sırayla.
- En son constructor gövdesi.
- Önce üst sınıf kurulur (
[static blok] <- ilk new'den önce, bir kez [instance blok] <- her new'de, constructor'dan önce [constructor] <- en son
Örnek 1 iki nesne oluşturarak static bloğun bir kez, instance bloğun ise her seferinde çalıştığını kanıtlar.
Ne zaman kullanmalı, ne zaman kaçınmalı?
- Static blok: Karmaşık statik veri kurulumu için iyi. Alternatif: statik bir fabrika metodu.
Static blokta atılan exception'lar
ExceptionInInitializerError'a yol açar ve sınıf yüklenemez; dikkatli ol. - Instance blok: Constructor'lar arası paylaşılan kod için kullanışlı; ancak çoğu durumda
ortak bir private başlatma metodu veya constructor zincirleme (
this(...)) daha okunaklı olabilir. Record'larda instance initializer block kullanılamaz (compact constructor kullan).
Özet
İki başlatma bloğunu öğrendik: her new'de constructor'dan önce çalışan ve constructor'lar arası
ortak kodu toplayan instance initializer block (Örnek 1) ve sınıf yüklenince bir kez çalışıp
karmaşık statik kurulum yapan static initializer block (Örnek 2). Ayrıca nesne kurulumunun tam
sırasını (static → instance blok → constructor) netleştirdik. Bu, OOP eksik konuları bölümünü
tamamlıyor.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: Instance initializer block (örnek başlatma bloğu) ve çalışma sırası.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 System.out.println(">> İlk nesne oluşturuluyor:");
7 new Urun("Klavye");
8 System.out.println("\n>> İkinci nesne oluşturuluyor:");
9 new Urun("Mouse");
10
11 System.out.println("""
12
13 --- Başlatma sırası (nesne oluşturulurken) ---
14 1) (yalnızca İLK kez) static alanlar + static bloklar — sınıf yüklenince, BİR KEZ.
15 2) Her 'new'de: üst sınıf kurulur, sonra:
16 - instance alan başlatmaları + instance initializer blokları (yazıldıkları SIRADA),
17 - en son CONSTRUCTOR gövdesi.
18 Instance initializer bloğu, birden çok constructor'ın PAYLAŞTIĞI başlatma kodunu
19 tek yerde toplamak için kullanılır (her constructor'dan önce çalışır).""");
20 }
21}
22
23class Urun {
24 // 1) static blok: sınıf ilk yüklendiğinde BİR KEZ çalışır.
25 static int uretilenSayisi;
26 static { uretilenSayisi = 0; System.out.println(" [static blok] Urun sınıfı yüklendi"); }
27
28 // 2) instance alan başlatma + instance initializer blok: HER new'de, constructor'dan ÖNCE.
29 private final String ad;
30 private final long olusturmaZamani = System.nanoTime();
31 { // instance initializer block
32 uretilenSayisi++;
33 System.out.println(" [instance blok] sayac=" + uretilenSayisi);
34 }
35
36 // 3) constructor: en son çalışır.
37 Urun(String ad) {
38 this.ad = ad;
39 System.out.println(" [constructor] ad=" + this.ad + ", zaman kaydı alındı=" + (olusturmaZamani > 0));
40 }
41}Ornek2
çalıştırılabilir1// Ornek2: Static initializer block — sınıf düzeyinde tek seferlik, karmaşık başlatma.
2// Çalıştırma: java Ornek2.java
3import java.util.Map;
4import java.util.HashMap;
5import java.util.Collections;
6
7public class Ornek2 {
8
9 public static void main(String[] args) {
10 // Statik tablo, sınıf yüklenince static blokta bir kez kurulmuştu.
11 System.out.println("USD kuru: " + DovizTablosu.kur("USD"));
12 System.out.println("EUR kuru: " + DovizTablosu.kur("EUR"));
13 System.out.println("Bilinmeyen: " + DovizTablosu.kur("XXX"));
14 System.out.println("Toplam para birimi: " + DovizTablosu.adet());
15
16 System.out.println("""
17
18 --- static initializer block ---
19 static { ... } bloğu, sınıf İLK yüklendiğinde BİR KEZ çalışır (tüm static alanlardan sonra,
20 herhangi bir nesne/static metot kullanılmadan önce).
21 Kullanım: tek satırda atanamayan KARMAŞIK statik başlatma — sabit tablolar/haritalar kurmak,
22 kaynak/yapılandırma yüklemek, hesaplanmış sabitler üretmek.
23 Basit atamalar için static blok gerekmez (alan başlatması yeter): static int X = 5;""");
24 }
25}
26
27class DovizTablosu {
28 private static final Map<String, Double> KURLAR;
29
30 // Karmaşık başlatma: bir Map'i doldurup değiştirilemez yap. Tek satıra sığmaz -> static blok.
31 static {
32 Map<String, Double> m = new HashMap<>();
33 m.put("USD", 32.50);
34 m.put("EUR", 35.10);
35 m.put("GBP", 41.20);
36 KURLAR = Collections.unmodifiableMap(m);
37 System.out.println("[static blok] döviz tablosu yüklendi (" + m.size() + " kayıt)");
38 }
39
40 static double kur(String kod) { return KURLAR.getOrDefault(kod, 0.0); }
41 static int adet() { return KURLAR.size(); }
42}