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.isimStatic (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); // 3toplamSayi 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 önerilmezNesne ü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); // falseMath 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ıyorsunNeden? Çü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şim | static field | instance field | static metot | instance 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/mydbstatic 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| Senaryo | static mi? | Neden? |
|---|---|---|
| Öğrencinin ismi | ❌ | Her öğ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: 3sonID 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)); // hahahaConstructor'ı 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
mainstatic çünkü program başladığında henüz nesne yok
AI Asistan
Sorularını yanıtlamaya hazır