Eğitim Portalı/Java/Enum ve Wrapper Sınıfları
Java01-java/10-enum-ve-wrapper

Enum ve Wrapper Sınıfları

Bu bölümde iki küçük ama günlük hayatta sık kullanılan konuyu ele alıyoruz. Enum, sabit ve sınırlı bir değer kümesini tip güvenli biçimde temsil eder (haftanın günleri, sipariş durumu, yönler). Wrapper sınıfları ise i…

Enum ve Wrapper Sınıfları

Bu bölümde iki küçük ama günlük hayatta sık kullanılan konuyu ele alıyoruz. Enum, sabit ve sınırlı bir değer kümesini tip güvenli biçimde temsil eder (haftanın günleri, sipariş durumu, yönler). Wrapper sınıfları ise ilkel tiplerin (int, double...) nesne karşılığıdır ve koleksiyonlarla, generics'le çalışırken kaçınılmazdır.

Enum

Bir değer yalnızca belirli birkaç seçenekten biri olabiliyorsa, onu String veya int ile temsil etmek hataya açıktır ("TODO" mu "Todo" mu?). enum bu seçenekleri sabit, tip güvenli bir küme olarak tanımlar:

enum Yon { KUZEY, GUNEY, DOGU, BATI }
Yon y = Yon.DOGU;          // sadece tanımlı değerler atanabilir

Enum'lar switch ile çok iyi çalışır (case'lerde adı sade yazarsın), values() ile tüm değerleri dizi olarak verir, valueOf("...") ile metinden enum'a çevirir, name() ve ordinal() ile adını ve sırasını okursun. Örnek 1 (./Ornek1.java) bunları gösterir.

Davranışlı enum'lar

Java'da enum sadece bir etiket değildir; tam bir sınıf gibi alan, constructor ve metot içerebilir. Hatta her sabit kendi davranışını verebilir. Bu, "her seçeneğin kendine özgü bir işi var" durumlarını çok zarif modeller:

enum Islem {
    TOPLA("+") { public double uygula(double a, double b) { return a + b; } },
    CARP("*")  { public double uygula(double a, double b) { return a * b; } };
    private final String sembol;
    Islem(String sembol) { this.sembol = sembol; }
    public abstract double uygula(double a, double b);
}

Örnek 2 (./Ornek2.java) dört aritmetik işlemi davranışlı bir enum olarak tanımlar ve hepsini tek döngüde uygular — if/switch yığını yerine temiz, genişletilebilir bir yapı.

Wrapper sınıfları

Her ilkel tipin bir nesne karşılığı (wrapper) vardır: intInteger, doubleDouble, booleanBoolean, charCharacter... Neden gerekir? Çünkü koleksiyonlar ve generics nesne tutar, ilkel tip tutamaz: List<int> yazamazsın, List<Integer> yazarsın.

Autoboxing ve unboxing

Java, ilkel tip ile wrapper arasında otomatik dönüşüm yapar:

List<Integer> liste = new ArrayList<>();
liste.add(5);          // autoboxing: int -> Integer
int ilk = liste.get(0); // unboxing: Integer -> int

Bu kolaylık genelde sorunsuzdur ama performans-kritik döngülerde gereksiz kutulama maliyet yaratabilir; orada int[] veya IntStream tercih edilir.

Parsing ve yardımcılar

Wrapper sınıfları metinden sayıya çevirmenin ve faydalı sabitlerin evidir:

Integer.parseInt("123");   // 123
Double.parseDouble("3.14"); // 3.14
Integer.MAX_VALUE;          // en büyük int

Dikkat: Integer cache tuzağı

Bu, ünlü bir tuzaktır. Java, -128..127 arası Integer nesnelerini önbelleğe alır. Bu aralıkta == aynı nesneyi gösterir (true), ama aralık dışında farklı nesneler oluşur:

Integer a = 100, b = 100;   a == b;  // true  (önbellek)
Integer c = 200, d = 200;   c == d;  // false (farklı nesne!)
c.equals(d);                          // true  (doğrusu bu)

Kural: Wrapper'ları değer olarak karşılaştırırken her zaman equals() kullan; == referans karşılaştırır ve seni yanıltır. Örnek 3 (./Ornek3.java) bunu canlı gösterir.

Özet

Enum ile sabit değer kümelerini tip güvenli, hatta davranışlı biçimde modellemeyi; wrapper sınıfları ile ilkel tipleri nesne dünyasına taşımayı, autoboxing/unboxing'i, parsing'i ve Integer önbellek tuzağını öğrendik. Sırada, modern Java'nın en sevilen özelliklerinden biri: lambda ifadeleri ve functional interface'ler.

Kod Örnekleri(3)

Ornek1

çalıştırılabilir
Ornek1.java
1// Ornek1: Enum temelleri — tanım, switch ve values().
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5    // Enum: sabit, sınırlı bir değer kümesi. Tip güvenlidir:
6    // sadece tanımlı değerler atanabilir, yanlış metin atanamaz.
7    enum Yon { KUZEY, GUNEY, DOGU, BATI }
8
9    static String aciklama(Yon yon) {
10        // switch ile enum: case'lerde enum adını sade yazarız (Yon.KUZEY değil, KUZEY).
11        return switch (yon) {
12            case KUZEY -> "yukarı";
13            case GUNEY -> "aşağı";
14            case DOGU  -> "sağa";
15            case BATI  -> "sola";
16        };
17    }
18
19    public static void main(String[] args) {
20        Yon y = Yon.DOGU;
21        System.out.println("Seçilen yön: " + y + " -> " + aciklama(y));
22
23        // values(): tüm enum değerlerini dizi olarak verir.
24        System.out.println("\nTüm yönler:");
25        for (Yon yon : Yon.values()) {
26            // ordinal(): tanım sırasındaki indeks; name(): metin adı.
27            System.out.printf("  %d) %s -> %s%n", yon.ordinal(), yon.name(), aciklama(yon));
28        }
29
30        // valueOf(): metinden enum'a çevirir (tam eşleşme gerekir).
31        Yon metindenGelen = Yon.valueOf("BATI");
32        System.out.println("\nvalueOf(\"BATI\") = " + metindenGelen);
33    }
34}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek2

çalıştırılabilir
Ornek2.java
1// Ornek2: Davranışlı enum — alan, constructor ve metot içeren enum.
2// Çalıştırma: java Ornek2.java
3public class Ornek2 {
4
5    // Enum'lar yalnızca sabit değil; alan, constructor ve metot da içerebilir.
6    // Her sabit, kendi davranışını uygulayabilir.
7    enum Islem {
8        TOPLA("+") { public double uygula(double a, double b) { return a + b; } },
9        CIKAR("-") { public double uygula(double a, double b) { return a - b; } },
10        CARP("*")  { public double uygula(double a, double b) { return a * b; } },
11        BOL("/")   { public double uygula(double a, double b) { return a / b; } };
12
13        private final String sembol;
14
15        // Enum constructor'ı private'tır; her sabit kendi sembolünü taşır.
16        Islem(String sembol) { this.sembol = sembol; }
17
18        public String sembol() { return sembol; }
19
20        // Soyut enum metodu: her sabit kendi sürümünü verir.
21        public abstract double uygula(double a, double b);
22    }
23
24    public static void main(String[] args) {
25        double a = 12, b = 4;
26        System.out.println("a = " + a + ", b = " + b + "\n");
27
28        // Tüm işlemleri tek döngüde uygula.
29        for (Islem islem : Islem.values()) {
30            System.out.printf("%.1f %s %.1f = %.2f%n", a, islem.sembol(), b, islem.uygula(a, b));
31        }
32    }
33}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek3

çalıştırılabilir
Ornek3.java
1// Ornek3: Wrapper sınıfları, autoboxing/unboxing, parsing ve Integer cache tuzağı.
2// Çalıştırma: java Ornek3.java
3import java.util.ArrayList;
4import java.util.List;
5
6public class Ornek3 {
7
8    public static void main(String[] args) {
9        // Wrapper: ilkel tiplerin nesne karşılığı (int->Integer, double->Double...).
10        // Koleksiyonlar ilkel tip tutamaz, wrapper tutar.
11        List<Integer> sayilar = new ArrayList<>();
12
13        // --- Autoboxing: int -> Integer otomatik ---
14        sayilar.add(5);       // 5 (int) otomatik Integer'a kutulanır
15        sayilar.add(10);
16
17        // --- Unboxing: Integer -> int otomatik ---
18        int ilk = sayilar.get(0); // Integer otomatik int'e açılır
19        System.out.println("Liste: " + sayilar + ", ilk eleman + 1 = " + (ilk + 1));
20
21        // --- Parsing: metinden sayıya ---
22        int x = Integer.parseInt("123");
23        double d = Double.parseDouble("3.14");
24        boolean b = Boolean.parseBoolean("true");
25        System.out.println("parseInt(\"123\")=" + x + ", parseDouble(\"3.14\")=" + d + ", parseBoolean=" + b);
26
27        // Wrapper sabitleri ve yardımcı metotlar:
28        System.out.println("Integer.MAX_VALUE = " + Integer.MAX_VALUE);
29        System.out.println("Integer.max(7, 3) = " + Integer.max(7, 3));
30
31        // --- Integer cache tuzağı ---
32        // Java, -128..127 arası Integer'ları önbelleğe alır; bu aralıkta == aynı nesneyi verir.
33        Integer a1 = 100, a2 = 100;       // önbellek aralığında
34        Integer b1 = 200, b2 = 200;       // önbellek dışında
35        System.out.println("\n--- Integer == tuzağı ---");
36        System.out.println("100 == 100 (Integer) : " + (a1 == a2)); // true (önbellek)
37        System.out.println("200 == 200 (Integer) : " + (b1 == b2)); // false (farklı nesne!)
38        System.out.println("200.equals(200)      : " + b1.equals(b2)); // true (doğrusu bu)
39        System.out.println("\nKural: Wrapper'ları DEĞER olarak karşılaştırırken equals() kullan.");
40    }
41}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.