Eğitim Portalı/Java/Sayı Wrapper Sınıfları ve Autoboxing
Java01-java/76-sayilar-ve-autoboxing

Sayı Wrapper Sınıfları ve Autoboxing

Java'da iki tür veri vardır: ilkel tipler (int, double, boolean, char...) ve nesneler. İlkel tipler hızlı ve kompakttır ama nesne değildir — metotları yoktur, null olamaz ve koleksiyonlarda (List<int> yazılamaz) kulla…

Sayı Wrapper Sınıfları ve Autoboxing

Java'da iki tür veri vardır: ilkel tipler (int, double, boolean, char...) ve nesneler. İlkel tipler hızlı ve kompakttır ama nesne değildir — metotları yoktur, null olamaz ve koleksiyonlarda (List<int> yazılamaz) kullanılamaz. Her ilkel tipin bir wrapper (sarmalayıcı) sınıfı vardır (Integer, Double, Boolean...) ve Java, ikisi arasında otomatik dönüşüm (autoboxing/unboxing) yapar. Bu konu hem wrapper'ların gücünü hem de autoboxing'in sinsi tuzaklarını ele alır.

Wrapper sınıfları

İlkelWrapperİlkelWrapper
intIntegerbooleanBoolean
longLongcharCharacter
doubleDoublebyteByte
floatFloatshortShort

Wrapper'lar nesne olduğundan metot ve sabit taşır:

Integer.parseInt("123");        // String -> int
Integer.valueOf(42);            // int -> Integer
Integer.MIN_VALUE; Integer.MAX_VALUE;
Integer.toBinaryString(255);    // "11111111"
Integer.parseInt("1010", 2);    // ikilik tabandan -> 10
Integer.compare(a, b); Integer.sum(a, b);

Neden gerekli? Koleksiyonlar ve jenerikler yalnızca nesne tutar (List<Integer>, Map<String,Integer>); ayrıca wrapper null olabilir ("değer yok" durumu). Örnek 1 (./Ornek1.java) wrapper metotlarını gösterir.

Autoboxing ve unboxing

Java, ilkel ↔ wrapper dönüşümünü otomatik yapar:

Integer kutulu = 5;        // autoboxing: int -> Integer
int ilkel = kutulu;        // unboxing: Integer -> int
list.add(10);              // autoboxing (koleksiyon nesne tutar)
int x = list.get(0);       // unboxing

Bu kolaylıktır — ama iki tehlikeli tuzağı vardır.

Tuzak 1: == ile wrapper karşılaştırma (Integer cache)

Integer.valueOf, −128..127 arasındaki değerler için bir önbellek kullanır (aynı nesneyi döndürür); bu aralığın dışında her seferinde yeni nesne üretir. Sonuç, == ile karşılaştırma yanıltıcı olur:

Integer a = 100, b = 100;   a == b  // true  (önbellek)
Integer c = 200, d = 200;   c == d  // FALSE (yeni nesneler!)
c.equals(d)                          // true  (DOĞRU yol)

Kural: Wrapper nesnelerini her zaman .equals() ile karşılaştır, asla == ile. (== referans karşılaştırır; ilkel int için sorun yoktur ama wrapper için tuzaktır.)

Tuzak 2: null unboxing → NullPointerException

Wrapper null olabilir; bir null wrapper'ı unbox etmek (ilkel'e çevirmek) NPE atar:

Integer belkiNull = null;
int x = belkiNull;    // unboxing -> null.intValue() -> NullPointerException

Özellikle veritabanından/Map'ten gelen, null olabilen değerleri ilkel'e atarken dikkat et. Örnek 2 (./Ornek2.java) her iki tuzağı canlı gösterir.

Performans notu

Sıkı döngülerde gereksiz autoboxing maliyetlidir (Long toplam = 0L; toplam += i; her adımda kutu/kutudan-çıkar). Yoğun sayısal işte ilkel tip kullan (long toplam), wrapper'ı yalnızca gerektiğinde (koleksiyon, null).

Özet

İlkel tiplerin wrapper karşılıklarını ve yardımcı metotlarını (Örnek 1); autoboxing/unboxing kolaylığını ve iki kritik tuzağını — == ile wrapper karşılaştırma (çözüm: equals) ve null unboxing NPE'si — (Örnek 2) öğrendik; performans notuna değindik. Sırada, karakter ve mantıksal veri sınıfları: Character ve Boolean.

Kod Örnekleri(2)

Ornek1

çalıştırılabilir
Ornek1.java
1// Ornek1: Wrapper (sarmalayıcı) sınıflar — Integer, Long, Double... ve yardımcı metotları.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5    public static void main(String[] args) {
6        // İlkel tip (int) vs sarmalayıcı (Integer): wrapper bir NESNEDİR, metotları/sabitleri vardır.
7
8        // Parse: String -> sayı
9        int sayi = Integer.parseInt("123");
10        double ondalik = Double.parseDouble("3.14");
11        System.out.println("parseInt: " + sayi + ", parseDouble: " + ondalik);
12
13        // valueOf: String/ilkel -> wrapper nesnesi
14        Integer kutulu = Integer.valueOf(42);
15        System.out.println("valueOf: " + kutulu);
16
17        // Sınırlar
18        System.out.println("\nInteger MIN/MAX: " + Integer.MIN_VALUE + " .. " + Integer.MAX_VALUE);
19        System.out.println("Long MAX        : " + Long.MAX_VALUE);
20        System.out.println("Double MAX      : " + Double.MAX_VALUE);
21
22        // Taban dönüşümleri
23        System.out.println("\n255 ikilik : " + Integer.toBinaryString(255));
24        System.out.println("255 onaltılık: " + Integer.toHexString(255));
25        System.out.println("'1010' (ikilik) -> " + Integer.parseInt("1010", 2));
26
27        // Karşılaştırma ve yardımcılar
28        System.out.println("\ncompare(3,9): " + Integer.compare(3, 9));
29        System.out.println("max(3,9): " + Integer.max(3, 9) + ", sum: " + Integer.sum(3, 9));
30        System.out.println("'A' karakter kodu (int): " + Integer.valueOf('A')); // 'A' kodu 65
31
32        System.out.println("""
33
34                --- Wrapper (sarmalayıcı) sınıflar ---
35                Her ilkel tipin bir nesne karşılığı vardır: int->Integer, long->Long, double->Double,
36                  boolean->Boolean, char->Character, byte/short/float->Byte/Short/Float.
37                Neden? Koleksiyonlar/jenerikler yalnızca NESNE tutar (List<Integer>, Map<...>); null olabilir.
38                Yararlı statikler: parseXxx (String->ilkel), valueOf, MIN/MAX_VALUE, toBinaryString/toHexString,
39                  compare/sum/max. Sonraki örnek: otomatik kutulama (autoboxing) ve tuzakları.""");
40    }
41}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek2

çalıştırılabilir
Ornek2.java
1// Ornek2: Autoboxing/unboxing ve iki klasik tuzak (Integer cache, null unboxing).
2// Çalıştırma: java Ornek2.java
3import java.util.ArrayList;
4import java.util.List;
5
6public class Ornek2 {
7
8    public static void main(String[] args) {
9        // AUTOBOXING: ilkel -> wrapper otomatik. UNBOXING: wrapper -> ilkel otomatik.
10        Integer kutulu = 5;        // autoboxing: int 5 -> Integer
11        int ilkel = kutulu;        // unboxing: Integer -> int
12        List<Integer> liste = new ArrayList<>();
13        liste.add(10);             // autoboxing (List nesne tutar)
14        int ilk = liste.get(0);    // unboxing
15        System.out.println("autobox/unbox: " + kutulu + ", " + ilkel + ", " + ilk);
16
17        // TUZAK 1: Integer cache. -128..127 arası Integer'lar ÖNBELLEKTEN gelir (aynı nesne);
18        // bu aralık dışı her valueOf YENİ nesne üretir. Bu yüzden '==' yanıltıcıdır!
19        Integer a1 = 100, a2 = 100;     // önbellekte -> aynı nesne
20        Integer b1 = 200, b2 = 200;     // önbellek dışı -> farklı nesne
21        System.out.println("\n100 == 100 ? " + (a1 == a2) + "   (önbellek -> true)");
22        System.out.println("200 == 200 ? " + (b1 == b2) + "   (önbellek dışı -> false!)");
23        System.out.println("200 .equals 200 ? " + b1.equals(b2) + "  (DOĞRU yol: equals)");
24
25        // TUZAK 2: null unboxing -> NullPointerException
26        Integer belkiNull = null;
27        try {
28            int patlar = belkiNull;   // unboxing: null.intValue() -> NPE
29            System.out.println(patlar);
30        } catch (NullPointerException e) {
31            System.out.println("\nnull unboxing -> NullPointerException (wrapper null olabilir!)");
32        }
33
34        System.out.println("""
35
36                --- Autoboxing tuzakları ---
37                Autoboxing/unboxing kolaylıktır ama iki tuzağı vardır:
38                1) Integer'ları '=='  ile KARŞILAŞTIRMA! -128..127 önbellekten (==true), dışı yeni nesne (==false).
39                   Wrapper karşılaştırmasında HER ZAMAN .equals() kullan.
40                2) null wrapper'ı unbox etmek NPE atar (Integer x = null; int y = x;).
41                   Olası null wrapper'ları unbox etmeden önce kontrol et.
42                Performans: döngülerde gereksiz autoboxing (Long toplam += ...) yavaşlatır; ilkel tip kullan.""");
43    }
44}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.