Inner Class ve Enum
Giriş
Java'da sınıflar her zaman ayrı dosyalarda yaşamaz. Bazen bir sınıf başka bir sınıfın içinde tanımlanır — buna inner class denir. Ayrıca sabit değer kümeleri için kullanılan enum tipi var. Bu derste ikisini de öğreneceğiz.
Inner Class Nedir?
Bir sınıfın içinde tanımlanan başka bir sınıf. Bunu bir kutu içinde kutu gibi düşün. Dış kutu (outer class) bir bütün, iç kutu (inner class) onun parçası.
class DiskKutu { // outer class
class Cikolata { // inner class
String tat;
}
}Neden inner class kullanırız?
İki sınıf mantıksal olarak çok sıkı bağlıysa
İç sınıf dış sınıfın private üyelerine erişmek istiyorsa
Kodu organize etmek için (dışarıya gereksiz sınıf göstermemek)
Java'da 4 tür inner class var. Sırayla görelim.
1. Non-static Inner Class (Üye İç Sınıf)
En temel inner class. Dış sınıfın bir üyesi gibi davranır.
class Araba {
private String marka;
private int hiz;
Araba(String marka) {
this.marka = marka;
this.hiz = 0;
}
// Inner class
class Motor {
private int beygir;
Motor(int beygir) {
this.beygir = beygir;
}
void bilgi() {
// Dış sınıfın private field'ına erişebilir!
System.out.println(marka + " motoru: " + beygir + " HP");
}
}
}Araba araba = new Araba("BMW");
Araba.Motor motor = araba.new Motor(240); // dikkat: araba.new
motor.bilgi(); // BMW motoru: 240 HPÖzellikler:
Dış sınıfın tüm üyelerine erişebilir (private dahil)
Bir dış nesne olmadan oluşturulamaz
Oluşturma sözdizimi:
disNesne.new IcSinif()
2. Static Inner Class (Statik İç Sınıf)
static keyword ile tanımlanır. Dış sınıfın nesnesine ihtiyaç duymaz.
class Universite {
String ad;
static int toplamOgrenci;
// Static inner class
static class Adres {
String sehir;
String ilce;
Adres(String sehir, String ilce) {
this.sehir = sehir;
this.ilce = ilce;
}
void yazdir() {
// static field'a erişebilir
System.out.println(sehir + "/" + ilce);
// System.out.println(ad); // HATA! instance field'a erişemez
}
}
}// Dış nesne gerekmez
Universite.Adres adres = new Universite.Adres("Istanbul", "Kadikoy");
adres.yazdir(); // Istanbul/KadikoyNon-static vs Static Inner Class
| Özellik | Non-static Inner | Static Inner |
|---|---|---|
| Dış nesne gerekli mi? | ✅ | ❌ |
| Dış instance field'a erişim | ✅ | ❌ |
| Dış static field'a erişim | ✅ | ✅ |
| Oluşturma | dis.new Ic() | new Dis.Ic() |
💡 İpucu: Eğer iç sınıf dış sınıfın instance üyelerine erişmiyorsa, static yap. Daha az bellek kullanır ve daha bağımsızdır. Çoğu durumda static inner class daha mantıklıdır.
3. Local Inner Class (Yerel İç Sınıf)
Metot içinde tanımlanan sınıf. Çok nadir kullanılır.
class Hesaplama {
void hesapla() {
// Metot içinde tanımlanmış sınıf
class Sonuc {
int deger;
Sonuc(int deger) { this.deger = deger; }
void yazdir() { System.out.println("Sonuç: " + deger); }
}
Sonuc s = new Sonuc(42);
s.yazdir();
}
}Bu sınıf sadece hesapla() metodu içinde kullanılabilir. Pratikte çok nadir karşılaşırsın, ama sınavlarda sorulabilir.
4. Anonymous Class (Anonim Sınıf)
İsmi olmayan, tek kullanımlık sınıf. Genellikle bir arayüzü (interface) veya sınıfı hızlıca implement etmek için kullanılır.
class Selamlayici {
void selamla() {
System.out.println("Merhaba!");
}
}
public class Main {
public static void main(String[] args) {
// Normal yol
Selamlayici s1 = new Selamlayici();
s1.selamla(); // Merhaba!
// Anonymous class — metodu override ediyoruz
Selamlayici s2 = new Selamlayici() {
@Override
void selamla() {
System.out.println("Selam dostum!");
}
};
s2.selamla(); // Selam dostum!
}
}new Selamlayici() { ... } — bu, Selamlayici'nın anonim alt sınıfını oluşturuyor ve anında metodu override ediyor.
Anonymous Class ile Sıralama
En yaygın kullanımı budur (ileride Lambda ile daha kısa yazacaksın):
ArrayList<String> isimler = new ArrayList<>(Arrays.asList("Zeynep", "Ali", "Mehmet"));
Collections.sort(isimler, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length(); // uzunluğa göre sırala
}
});
System.out.println(isimler); // [Ali, Zeynep, Mehmet]Anonymous class'lar Java 8'den önce çok kullanılırdı. Artık Lambda ile çoğu yerde gereksiz oldu, ama hâlâ karşına çıkar.
Enum Nedir?
Enum (enumeration), sabit değerler kümesi tanımlamak için kullanılan özel bir tiptir.
Haftanın günlerini düşün. 7 tane var, hiç değişmiyor. Bunları String ile tutabilirsin: "PAZARTESI", "SALI"... Ama birisi yanlışlıkla "PAZRTESI" yazabilir ve Java bunu yakalayamaz.
Enum ile bu sorun ortadan kalkar:
enum Gun {
PAZARTESI, SALI, CARSAMBA, PERSEMBE, CUMA, CUMARTESI, PAZAR
}Gun bugun = Gun.CUMA;
System.out.println(bugun); // CUMA
// Gun bugun = Gun.PAZRTESI; // DERLEME HATASI! Böyle bir değer yokEnum sayesinde tür güvenliği sağlanır. Sadece tanımlanan değerler kullanılabilir.
Enum Tanımlama ve Kullanma
enum Renk {
KIRMIZI, YESIL, MAVI, SARI, BEYAZ, SIYAH
}
enum Mevsim {
ILKBAHAR, YAZ, SONBAHAR, KIS
}
enum Boyut {
KUCUK, ORTA, BUYUK, EKSTRA_BUYUK
}Renk favori = Renk.MAVI;
Mevsim simdi = Mevsim.KIS;
System.out.println(favori); // MAVI
System.out.println(simdi); // KISEnum ile switch
Enum'lar switch ile mükemmel çalışır:
Gun gun = Gun.CUMARTESI;
switch (gun) {
case PAZARTESI:
case SALI:
case CARSAMBA:
case PERSEMBE:
case CUMA:
System.out.println("İş günü");
break;
case CUMARTESI:
case PAZAR:
System.out.println("Hafta sonu!");
break;
}⚠️ Dikkat: switch içinde Gun.CUMARTESI değil, sadece CUMARTESI yazılır. Türü zaten Gun olduğu biliniyor.
Enum ile if Karşılaştırma
Gun gun = Gun.PAZAR;
if (gun == Gun.PAZAR) {
System.out.println("Bugün tatil!");
}Enum'larda == kullanabilirsin. String gibi .equals() gerekmez çünkü enum değerleri singleton'dır — her değerden sadece bir tane var.
Enum Metotları
Her enum'un hazır metotları var:
// values() — tüm değerleri dizi olarak döndürür
Gun[] gunler = Gun.values();
for (Gun g : gunler) {
System.out.println(g);
}
// ordinal() — sıra numarası (0'dan başlar)
System.out.println(Gun.PAZARTESI.ordinal()); // 0
System.out.println(Gun.CUMA.ordinal()); // 4
// name() — String olarak adı
System.out.println(Gun.CUMA.name()); // "CUMA"
// valueOf() — String'den enum'a dönüştür
Gun gun = Gun.valueOf("SALI");
System.out.println(gun); // SALI
// Geçersiz değer → IllegalArgumentException
// Gun.valueOf("TATIL"); // HATA!Enum'a Field ve Metot Ekleme
Enum sadece basit sabitler değil — içine field, constructor ve metot eklenebilir.
enum Gezegen {
MERKUR(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
DUNYA(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6);
private final double kutle; // kg
private final double yaricap; // metre
// Enum constructor — her zaman private
Gezegen(double kutle, double yaricap) {
this.kutle = kutle;
this.yaricap = yaricap;
}
double getKutle() { return kutle; }
double getYaricap() { return yaricap; }
// Yüzey yerçekimi hesabı
double yuzeyYercekimi() {
final double G = 6.67300E-11;
return G * kutle / (yaricap * yaricap);
}
}for (Gezegen g : Gezegen.values()) {
System.out.printf("%s: yerçekimi = %.2f m/s²%n",
g, g.yuzeyYercekimi());
}⚠️ Dikkat: Enum constructor her zaman private'tır (yazmasanız bile). Dışarıdan new Gezegen(...) yapılamaz — enum değerleri sadece enum bloğu içinde tanımlanır.
Daha Basit Bir Örnek
enum Boyut {
KUCUK("S", 29.99),
ORTA("M", 39.99),
BUYUK("L", 49.99),
EKSTRA_BUYUK("XL", 59.99);
private final String kisaltma;
private final double fiyat;
Boyut(String kisaltma, double fiyat) {
this.kisaltma = kisaltma;
this.fiyat = fiyat;
}
public String getKisaltma() { return kisaltma; }
public double getFiyat() { return fiyat; }
}Boyut secim = Boyut.ORTA;
System.out.println(secim.getKisaltma()); // M
System.out.println(secim.getFiyat()); // 39.99Enum Ne Zaman Kullanılır?
Sabit değer kümeleri: Günler, mevsimler, renkler, yönler
Durum (state):
AKTIF,PASIF,BEKLEMEDETip güvenliği: String yerine enum kullanarak yazım hatalarını önle
switch ile çalışma: Belirlı durumları kontrol et
// KÖTÜ — String ile
String durum = "aktf"; // yazım hatası, Java yakalaYAMAZ
// İYİ — Enum ile
enum Durum { AKTIF, PASIF, BEKLEMEDE }
Durum durum = Durum.AKTIF; // yazım hatası → derleme hatasıPratik Örnek: Sipariş Durumu
enum SiparisDurum {
OLUSTURULDU("Sipariş oluşturuldu"),
HAZIRLANIYOR("Sipariş hazırlanıyor"),
KARGODA("Kargoya verildi"),
TESLIM_EDILDI("Teslim edildi"),
IPTAL("İptal edildi");
private final String aciklama;
SiparisDurum(String aciklama) {
this.aciklama = aciklama;
}
public String getAciklama() { return aciklama; }
public boolean iptalEdilebilirMi() {
return this == OLUSTURULDU || this == HAZIRLANIYOR;
}
}SiparisDurum durum = SiparisDurum.KARGODA;
System.out.println(durum.getAciklama()); // Kargoya verildi
System.out.println(durum.iptalEdilebilirMi()); // false
SiparisDurum yeni = SiparisDurum.OLUSTURULDU;
System.out.println(yeni.iptalEdilebilirMi()); // trueInner Class ve Enum Birlikte
Enum aslında özel bir inner class gibi de kullanılabilir:
class Oyun {
enum Zorluk {
KOLAY, ORTA, ZOR
}
private Zorluk zorluk;
private int skor;
Oyun(Zorluk zorluk) {
this.zorluk = zorluk;
this.skor = 0;
}
void puanKazan() {
switch (zorluk) {
case KOLAY: skor += 10; break;
case ORTA: skor += 25; break;
case ZOR: skor += 50; break;
}
System.out.println("Skor: " + skor);
}
}Oyun oyun = new Oyun(Oyun.Zorluk.ZOR);
oyun.puanKazan(); // Skor: 50
oyun.puanKazan(); // Skor: 100Özet
Inner class başka bir sınıfın içinde tanımlanan sınıftır; dış sınıfın private üyelerine erişebilir
Static inner class dış nesneye ihtiyaç duymaz; iç sınıf dış instance'a erişmiyorsa static yap
Anonymous class ismi olmayan, tek kullanımlık sınıftır; genellikle interface implement etmek için
Enum sabit değer kümeleri tanımlar; tür güvenliği sağlar, switch ile mükemmel çalışır
Enum'a field, constructor ve metot eklenebilir; constructor her zaman private'tır
Enum kullan: günler, mevsimler, durumlar, tipler gibi sabit kümelerde
AI Asistan
Sorularını yanıtlamaya hazır