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: int→Integer, double→Double,
boolean→Boolean, char→Character... 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ılabilir1// 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}Ornek2
çalıştırılabilir1// 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}Ornek3
çalıştırılabilir1// 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}