← Kursa Dön
📄 Text · 12 min

static Anahtar Kelimesi

Giriş

Şimdiye kadar oluşturduğumuz her şey nesneye bağlıydı. Her nesnenin kendi isim'i, kendi yas'ı, kendi bakiye'si vardı. Bu mantıklı — Ali'nin bakiyesi Ayşe'ninkinden farklı.

Ama bazı şeyler nesneye değil, sınıfın kendisine aittir. Mesela "toplam öğrenci sayısı" — bu tek bir öğrencinin değil, tüm sınıfın bilgisi. Veya bir yardımcı metot: Math.sqrt(25) — burada bir Math nesnesi oluşturmuyorsun, sınıf üzerinden direkt çağırıyorsun.

İşte static keyword bu durumlarda kullanılır. static olan şeyler sınıfa aittir, nesneye değil.

static Nedir?

Bunu bir sınıf tahtası analojisiyle düşün. Her öğrencinin kendi defteri var (instance field). Ama sınıfta bir tane tahta var — herkes aynı tahtayı görüyor (static field). Tahtaya bir şey yazdığında tüm öğrenciler görür.

  • Instance (nesne) üyesi: Her nesnede ayrı kopya. ali.isim ≠ ayse.isim

  • Static (sınıf) üyesi: Tüm nesneler arasında ortak. Tek kopya.

static Field

class Ogrenci {
    String isim;              // instance field — her öğrencide farklı
    static int toplamSayi = 0; // static field — tüm öğrenciler için tek

    Ogrenci(String isim) {
        this.isim = isim;
        toplamSayi++;  // her yeni öğrenci oluşturulduğunda artır
    }
}
Ogrenci ali = new Ogrenci("Ali");
System.out.println(Ogrenci.toplamSayi); // 1

Ogrenci ayse = new Ogrenci("Ayse");
System.out.println(Ogrenci.toplamSayi); // 2

Ogrenci mehmet = new Ogrenci("Mehmet");
System.out.println(Ogrenci.toplamSayi); // 3

toplamSayi bellekte tek bir yerde tutuluyor. Hangi nesneden erişirsen eriş, aynı değer.

Erişim

static field'a sınıf adıyla erişmek best practice'dir:

System.out.println(Ogrenci.toplamSayi);  // tercih edilen
System.out.println(ali.toplamSayi);       // çalışır ama önerilmez

Nesne üzerinden erişmek kafa karıştırır — sanki nesneye ait bir field gibi görünür ama değildir.

static Field Kullanım Alanları

class Ayarlar {
    static final String APP_ADI = "OgrenciSistemi";  // sabit
    static final String VERSIYON = "2.1.0";
    static final int MAX_OGRENCI = 500;
}

class BankaHesabi {
    static double faizOrani = 0.15;  // tüm hesaplar için aynı faiz
    private double bakiye;
}

class IDGenerator {
    private static int sonID = 0;  // ID üreteci

    static int yeniID() {
        return ++sonID;
    }
}

💡 İpucu: static final ile tanımlanan değişkenler sabit (constant) olur. Convention olarak BÜYÜK_HARF_ALT_ÇİZGİ ile yazılırlar: MAX_SIZE, DEFAULT_COLOR, PI.

static Method

Static metotlar nesne oluşturmadan çağrılabilir. Sınıf adıyla direkt çağırılır.

class MatemartikYardimci {
    static int topla(int a, int b) {
        return a + b;
    }

    static int kareAl(int sayi) {
        return sayi * sayi;
    }

    static boolean ciftMi(int sayi) {
        return sayi % 2 == 0;
    }
}

// Kullanım — nesne oluşturmaya gerek yok
int sonuc = MatemartikYardimci.topla(5, 3);       // 8
int kare = MatemartikYardimci.kareAl(4);           // 16
boolean cift = MatemartikYardimci.ciftMi(7);       // false

Math Sınıfı — En Bilinen static Örneği

Java'nın Math sınıfı tamamen static metotlardan oluşur:

double karekkok = Math.sqrt(25);        // 5.0
double us = Math.pow(2, 10);            // 1024.0
int mutlak = Math.abs(-42);             // 42
double rastgele = Math.random();         // 0.0 ile 1.0 arası
int buyuk = Math.max(15, 23);           // 23
double pi = Math.PI;                     // 3.141592653589793

// Hiçbirinde new Math() yapmıyorsun

Neden? Çünkü Math sınıfının nesne oluşturmasına gerek yok. Sadece hesaplama yapan yardımcı metotlar sunuyor. Bu tür sınıflara utility class denir.

static Method Kuralları

static metot instance field'a erişemez:

class Ogrenci {
    String isim;                // instance field
    static int toplamSayi = 0; // static field

    static void bilgiGoster() {
        System.out.println(toplamSayi);  // OK — static field'a erişebilir
        System.out.println(isim);        // HATA! — instance field'a erişemez
    }
}

Neden? static metot nesneye bağlı değil. Hangi nesnenin isim'ini gösterecek? Belli değil. Bu yüzden erişemez.

Instance metot her şeye erişebilir:

class Ogrenci {
    String isim;
    static int toplamSayi;

    void bilgiGoster() {                           // instance metot
        System.out.println(isim);                   // OK — instance field
        System.out.println(toplamSayi);             // OK — static field de erişilebilir
    }
}

Özet tablo:

Erişimstatic fieldinstance fieldstatic metotinstance metot
static metot
instance metot

⚠️ Dikkat: static metotlarda this kullanılamaz. this "bu nesne" demek — static metot nesneye bağlı değil, dolayısıyla this anlamsız.

main Metodu Neden static?

public static void main(String[] args) {
    // ...
}

main metodu static çünkü program başladığında henüz hiçbir nesne yok. JVM bir nesne oluşturmadan main'i çağırabilmeli — bu yüzden static.

Bu aynı zamanda main içinde direkt instance metot çağıramamanın nedeni:

public class App {
    String mesaj = "Merhaba";

    void selamVer() {
        System.out.println(mesaj);
    }

    public static void main(String[] args) {
        selamVer();  // HATA! static metottan instance metot çağrılamaz

        // Çözüm: nesne oluştur
        App app = new App();
        app.selamVer();  // çalışır
    }
}

static Block (Statik Başlatıcı Blok)

static field'ları başlatmak için kullanılır. Sınıf belleğe yüklendiğinde bir kez çalışır.

class Veritabani {
    static String connectionUrl;
    static int maxConnection;

    static {
        System.out.println("Veritabanı ayarları yükleniyor...");
        connectionUrl = "jdbc:mysql://localhost:3306/mydb";
        maxConnection = 10;
        System.out.println("Ayarlar yüklendi.");
    }
}
// Sınıfa ilk erişildiğinde static blok çalışır
System.out.println(Veritabani.connectionUrl);
// Çıktı:
// Veritabanı ayarları yükleniyor...
// Ayarlar yüklendi.
// jdbc:mysql://localhost:3306/mydb

static blok özellikle karmaşık başlatma işlemlerinde kullanılır — dosya okuma, konfigürasyon yükleme gibi.

Birden Fazla static Block

class Ornek {
    static int a;
    static int b;

    static {
        a = 10;
        System.out.println("Blok 1: a = " + a);
    }

    static {
        b = 20;
        System.out.println("Blok 2: b = " + b);
    }
}

Birden fazla static block tanılanabilir. Yazıldıkları sırayla çalışırlar.

static vs Instance — Karar Rehberi

Kendine şu soruyu sor: "Bu bilgi/davranış nesneye mi yoksa sınıfa mı ait?"

Nesnenin kendi verisi mi?
  Evet → instance field
  Hayır → static field

Nesne olmadan çağrılabilmeli mi?
  Evet → static method
  Hayır → instance method
Senaryostatic mi?Neden?
Öğrencinin ismiHer öğrencide farklı
Toplam öğrenci sayısıTüm sınıf için tek
Math.sqrt()Nesne gerektirmiyor
hesap.paraCek()Hangi hesaptan çekilecek?
Sabit değerler (PI, MAX_VALUE)Değişmeyen, sınıfa ait

Pratik Örnek: Sayaçlı Sınıf

class Calisan {
    private static int sonID = 0;
    private static int toplamCalisan = 0;

    private int id;
    private String isim;
    private double maas;

    public Calisan(String isim, double maas) {
        this.id = ++sonID;  // otomatik artan ID
        this.isim = isim;
        this.maas = maas;
        toplamCalisan++;
    }

    public void bilgiGoster() {
        System.out.println("ID: " + id + " | " + isim + " | " + maas + " TL");
    }

    public static int getToplamCalisan() {
        return toplamCalisan;
    }

    public static void istatistikGoster() {
        System.out.println("Toplam çalışan: " + toplamCalisan);
        System.out.println("Son verilen ID: " + sonID);
    }
}
Calisan c1 = new Calisan("Ali", 15000);
Calisan c2 = new Calisan("Ayse", 18000);
Calisan c3 = new Calisan("Mehmet", 16000);

c1.bilgiGoster();  // ID: 1 | Ali | 15000.0 TL
c2.bilgiGoster();  // ID: 2 | Ayse | 18000.0 TL
c3.bilgiGoster();  // ID: 3 | Mehmet | 16000.0 TL

Calisan.istatistikGoster();
// Toplam çalışan: 3
// Son verilen ID: 3

sonID ve toplamCalisan static çünkü tüm nesneler arasında ortak. id, isim, maas instance çünkü her çalışanda farklı.

Utility Class Pattern

Sadece static metotlardan oluşan sınıf:

class StringUtils {
    // Private constructor — nesne oluşturmayı engelle
    private StringUtils() { }

    public static boolean boslukMu(String s) {
        return s == null || s.trim().isEmpty();
    }

    public static String buyukHarfYap(String s) {
        if (boslukMu(s)) return s;
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    public static String tekrarla(String s, int kez) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < kez; i++) {
            sb.append(s);
        }
        return sb.toString();
    }
}

// Kullanım
System.out.println(StringUtils.boslukMu(""));          // true
System.out.println(StringUtils.buyukHarfYap("merhaba")); // Merhaba
System.out.println(StringUtils.tekrarla("ha", 3));       // hahaha

Constructor'ı private yapmak, dışarıdan new StringUtils() yazılmasını engeller. Zaten nesne oluşturmanın bir anlamı yok — tüm metotlar static.

Yaygın Hatalar

Hata 1: static metottan instance field/metoda erişmek

class Ornek {
    String isim;
    static void yazdir() {
        System.out.println(isim);  // HATA!
    }
}

Hata 2: static metotta this kullanmak

static void bilgi() {
    System.out.println(this.isim);  // HATA! static'te this yok
}

Hata 3: Her şeyi static yapmak

// KÖTÜ — bu OOP değil, prosedürel programlama
class Ogrenci {
    static String isim;    // tüm öğrenciler aynı isme mi sahip?
    static int yas;        // tüm öğrenciler aynı yaşta mı?
}

Özet

  • static olan şeyler sınıfa aittir, nesneye değil — bellekte tek kopya

  • static field: tüm nesneler arasında paylaşılan veri (sayaçlar, sabitler)

  • static method: nesne oluşturmadan çağrılan metot (Math.sqrt(), Arrays.sort())

  • static block: sınıf yüklendiğinde bir kez çalışır, karmaşık başlatma için

  • static metot instance üyelere erişemez, instance metot her şeye erişebilir

  • main static çünkü program başladığında henüz nesne yok