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ı
| İlkel | Wrapper | İlkel | Wrapper | |
|---|---|---|---|---|
int | Integer | boolean | Boolean | |
long | Long | char | Character | |
double | Double | byte | Byte | |
float | Float | short | Short |
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; ilkelintiç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ılabilir1// 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}Ornek2
çalıştırılabilir1// 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}