← Kursa Dön
📄 Text · 10 min

Initializer Block ve Nesne Başlatma

Giriş

Constructor'ı biliyorsun — nesne oluşturulurken field'lara değer atamak için kullanılıyordu. static blok da gördük — sınıf yüklendiğinde çalışıyordu. Peki ya her nesne oluşturulurken, ama constructor'dan önce çalışan bir kod bloğu olsaydı?

İşte instance initializer block tam bu. Constructor, static block ve initializer block birlikte Java'nın başlatma mekanizmasını oluşturur. Bu derste hepsinin nasıl çalıştığını ve çalışma sırasını net olarak öğreneceksin.

Instance Initializer Block

Süslü parantezler içinde, metot dışında, static keyword'ü olmadan yazılan kod bloğu:

class Ornek {
    int sayi;

    // Instance initializer block
    {
        sayi = 42;
        System.out.println("Instance initializer çalıştı");
    }

    Ornek() {
        System.out.println("Constructor çalıştı");
    }
}
Ornek o = new Ornek();
// Çıktı:
// Instance initializer çalıştı
// Constructor çalıştı

Instance initializer block, her nesne oluşturulduğunda, constructor'dan önce çalışır.

Instance Initializer'ın bir ortak başlatma kodu gibi düşün

Bunu bir otel odası hazırlığı gibi düşün. Her misafir gelmeden önce oda temizlenir, çarşaflar değiştirilir (initializer block). Sonra misafirin özel istekleri karşılanır — ekstra yastık, mini bar (constructor). Her misafir için temel hazırlık aynı, özel istekler farklı.

Neden Instance Initializer Kullanılır?

1. Birden Fazla Constructor'da Ortak Kod

class Kullanici {
    String isim;
    String rol;
    ArrayList<String> loglar;

    // Bu kod her constructor'da tekrarlanırdı
    {
        loglar = new ArrayList<>();
        loglar.add("Nesne oluşturuldu: " + java.time.LocalDateTime.now());
    }

    Kullanici(String isim) {
        this.isim = isim;
        this.rol = "USER";
    }

    Kullanici(String isim, String rol) {
        this.isim = isim;
        this.rol = rol;
    }
}

Her iki constructor'dan önce de loglar başlatılıyor. Constructor chaining (this()) ile de yapılabilirdi, ama bazen initializer block daha temiz.

2. Anonymous Class'larda Constructor Yazılamaz

Anonymous class'ların ismi olmadığı için constructor yazılamaz. Initializer block burada tek seçenek:

Runnable gorev = new Runnable() {
    // Constructor yazamayız — isim yok!

    // Initializer block ile başlatma
    {
        System.out.println("Görev hazırlanıyor...");
    }

    @Override
    public void run() {
        System.out.println("Görev çalışıyor.");
    }
};

Bu, instance initializer block'un en meşru kullanım alanıdır.

Static Initializer Block (Tekrar)

Önceki derste kısaca gördük, şimdi karşılaştırma amacıyla tekrar bakalım:

class Veritabani {
    static String url;
    static int port;

    // Static initializer — sınıf yüklendiğinde BİR KEZ çalışır
    static {
        url = "localhost";
        port = 3306;
        System.out.println("Static initializer çalıştı");
    }
}
System.out.println(Veritabani.url);
System.out.println(Veritabani.url);
// Çıktı:
// Static initializer çalıştı
// localhost
// localhost

Static blok sadece bir kez çalışır, sınıf belleğe ilk yüklendiğinde.

Static vs Instance Initializer

ÖzellikStatic InitializerInstance Initializer
Keywordstatic { }{ }
Ne zaman çalışırSınıf yüklendiğindeHer nesne oluşturulduğunda
Kaç kez çalışır1 kezNesne sayısı kadar
Neye erişirSadece static üyelereHem static hem instance

Çalışma Sırası — Kritik Konu

Bu kısım sınavlarda ve mülakatlarda çok sorulur. Sırayı doğru bilmek gerekir.

Temel Sıra

class Sira {
    static int staticField = degerVer("1. Static field");

    int instanceField = degerVer("3. Instance field");

    static {
        System.out.println("2. Static initializer block");
    }

    {
        System.out.println("4. Instance initializer block");
    }

    Sira() {
        System.out.println("5. Constructor");
    }

    static int degerVer(String mesaj) {
        System.out.println(mesaj);
        return 0;
    }
}
System.out.println("--- İlk nesne ---");
Sira s1 = new Sira();
System.out.println("--- İkinci nesne ---");
Sira s2 = new Sira();

Çıktı:

--- İlk nesne ---
1. Static field
2. Static initializer block
3. Instance field
4. Instance initializer block
5. Constructor
--- İkinci nesne ---
3. Instance field
4. Instance initializer block
5. Constructor

Sıra Kuralı

  1. Static üyeler (field + static blok) — sınıf yüklendiğinde, bir kez, yazıldıkları sırayla

  2. Instance üyeler (field + instance blok) — her nesne oluşturulduğunda, yazıldıkları sırayla

  3. Constructor — en son

Formül:

Static field/block (1 kez) → Instance field/block (her new'de) → Constructor (her new'de)

⚠️ Dikkat: Static başlatma sadece ilk nesne oluşturulduğunda (veya sınıfa ilk erişildiğinde) yapılır. İkinci nesnede static kısım tekrar çalışmaz.

Birden Fazla Blok

Birden fazla static ve instance blok olabilir. Yazıldıkları sırayla çalışırlar:

class CokBlok {
    {
        System.out.println("Instance blok 1");
    }

    {
        System.out.println("Instance blok 2");
    }

    static {
        System.out.println("Static blok 1");
    }

    static {
        System.out.println("Static blok 2");
    }

    CokBlok() {
        System.out.println("Constructor");
    }
}
new CokBlok();

Çıktı:

Static blok 1
Static blok 2
Instance blok 1
Instance blok 2
Constructor

Pratik Örnek: ID Üreteci

class Siparis {
    private static int sayac;
    private static final String PREFIX;

    // Static başlatma
    static {
        sayac = 1000;
        PREFIX = "SIP";
        System.out.println("Sipariş sistemi başlatıldı.");
    }

    private String siparisNo;
    private String urun;
    private java.time.LocalDateTime olusturmaZamani;

    // Instance başlatma — her sipariş için
    {
        sayac++;
        siparisNo = PREFIX + "-" + sayac;
        olusturmaZamani = java.time.LocalDateTime.now();
    }

    Siparis(String urun) {
        this.urun = urun;
    }

    void bilgiGoster() {
        System.out.println(siparisNo + " | " + urun + " | " + olusturmaZamani);
    }
}
Siparis s1 = new Siparis("Laptop");
Siparis s2 = new Siparis("Telefon");
Siparis s3 = new Siparis("Kulaklık");

s1.bilgiGoster();  // SIP-1001 | Laptop | ...
s2.bilgiGoster();  // SIP-1002 | Telefon | ...
s3.bilgiGoster();  // SIP-1003 | Kulaklık | ...

Static blok sistemi bir kez başlatıyor. Instance blok her siparişe otomatik numara ve zaman atıyor. Constructor sadece ürüne özel bilgiyi alıyor.

Ne Zaman Kullanılır?

Instance Initializer Kullan:

  • Anonymous class'larda (constructor yazılamadığı için)

  • Tüm constructor'larda ortak olan karmaşık başlatma kodu varsa

Instance Initializer Kullanma:

  • Basit atamalar için → direkt field tanımında yap: int x = 5;

  • Constructor'da yapılabilecek şeyler için → constructor daha okunabilir

Static Initializer Kullan:

  • Static field'ların karmaşık başlatması (dosya okuma, konfigürasyon)

  • Exception fırlatabilecek static başlatmalar

Static Initializer Kullanma:

  • Basit sabit atamalar için → static final int X = 5; yeterli

💡 İpucu: Pratikte instance initializer block çok sık kullanılmaz. Constructor çoğu durumda yeterli ve daha okunabilir. Ama çalışma sırasını bilmek, mülakat ve sınavlar için çok önemli. Static initializer ise gerçek projelerde konfigürasyon yüklemek için sıkça kullanılır.

Field Başlatma Yolları — Karşılaştırma

class Ornek {
    // Yol 1: Doğrudan atama
    int a = 10;

    // Yol 2: Instance initializer
    int b;
    {
        b = 20;
    }

    // Yol 3: Constructor
    int c;
    Ornek() {
        c = 30;
    }

    // Yol 4: Static (static field için)
    static int d = 40;

    // Yol 5: Static initializer (static field için)
    static int e;
    static {
        e = 50;
    }
}

Hangisini ne zaman?

  • Basit değer → doğrudan atama (int a = 10;)

  • Karmaşık hesaplama gerekiyorsa → constructor veya initializer

  • Static field → doğrudan atama veya static blok

  • Her constructor'da lazım + anonymous class → instance initializer

Yaygın Sınav Sorusu

class Test {
    static { System.out.print("A "); }
    { System.out.print("B "); }
    Test() { System.out.print("C "); }
    { System.out.print("D "); }
    static { System.out.print("E "); }
}

public class Main {
    public static void main(String[] args) {
        new Test();
        System.out.println();
        new Test();
    }
}

Çıktı:

A E B D C 
B D C

Açıklama:

  1. İlk new Test(): Static bloklar (A, E) → Instance bloklar (B, D) → Constructor (C)

  2. İkinci new Test(): Static bloklar çalışmaz (zaten çalıştı) → Instance bloklar (B, D) → Constructor (C)

Özet

  • Instance initializer block ({ }) her nesne oluşturulduğunda, constructor'dan önce çalışır

  • Static initializer block (static { }) sınıf yüklendiğinde bir kez çalışır

  • Çalışma sırası: static field/block → instance field/block → constructor

  • Instance initializer en çok anonymous class'larda kullanılır (constructor yazılamadığı için)

  • Static initializer konfigürasyon yükleme gibi karmaşık static başlatmalar için kullanılır

  • Birden fazla blok varsa yazıldıkları sırayla çalışırlar