-
Sadrazamv4
ig:sadrazam_v4 tg: Sadrazam.spy
🚀 BAŞTAN SONA JAVA DİLİ BÖLÜM-17: Generics (Jenerik Yapılar) ve Tip Güvenliği 🧬
Selamlar! Serimizin 17. bölümüne hoş geldiniz.
Önceki bölümde `try-catch-finally` bloklarını, Checked/Unchecked istisnaları ve özel Custom Exception sınıfları yazmayı görmüştük. Bu bölümde ise kodlarımızda tip güvenliğini (Type Safety) sağlayan, `ClassCastException` hatalarını derleme zamanında engelleyen ve esnek yapılar kurmamıza imkan tanıyan **Generics (Jenerik Yapılar)** konusunu işleyeceğiz.
---
📌 1. Generics Nedir ve Neden İhtiyaç Duyulur? 🛡️
Java 5 öncesinde koleksiyonlar gibi yapılarda her şey `Object` tipinde tutulurdu. Bu durum iki temel soruna yol açıyordu:
1. Her veri okunurken elle tip dönüşümü (Explicit Casting) yapmak gerekiyordu.
2. Hatalı tip atamaları derleme zamanında değil, uygulama çalışırken (`Runtime`) `ClassCastException` hatası veriyordu.
**Generics**; sınıfların, arayüzlerin ve metotların çalışacağı veri tiplerinin parametre olarak belirlenmesini sağlar.
### Generics'in Avantajları:
✨ **Tip Güvenliği (Type Safety):** Hatalı veri tipleri daha derleme aşamasında (`Compile-Time`) tespit edilir.
✨ **Casting İhtiyacının Ortadan Kalkması:** Tür dönüşümü kodlarına gerek kalmaz.
✨ **Kodun Yeniden Kullanılabilirliği:** Farklı veri tipleri için tek bir sınıf veya metot yazılabilir.
---
🏛️ 2. Jenerik Sınıf (Generic Class) Tanımlama ⚙️
Jenerik sınıflar tanımlanırken sınıf isminin yanına elmas operatörü `<T>` eklenir.
Sık Kullanılan Tip Parametre İsimlendirmeleri:
• `T` -> Type (Tip)
• `E` -> Element (Koleksiyon elemanı)
• `K` -> Key (Anahtar)
• `V` -> Value (Değer)
• `N` -> Number (Sayısal Tipler)
### Jenerik Kutusu Sınıfı (`Kutu.java`):
public class Kutu<T> {
private T icerik;
public void ekle(T icerik) {
this.icerik = icerik;
}
public T getIcerik() {
return icerik;
}
}
### Kullanımı (`Main.java`):
public class Main {
public static void main(String[] args) {
// String tipi için Kutu nesnesi
Kutu<String> metinKutusu = new Kutu<>();
metinKutusu.ekle("Java Generics Eğitimi");
String metin = metinKutusu.getIcerik(); // Explicit Cast GEREKMEDİ!
System.out.println("Metin: " + metin);
// Integer tipi için Kutu nesnesi
Kutu<Integer> sayiKutusu = new Kutu<>();
sayiKutusu.ekle(100);
int sayi = sayiKutusu.getIcerik();
System.out.println("Sayı: " + sayi);
// HATA! Derleyici tipi kontrol ettiği için yanlış veri engellenir:
// sayiKutusu.ekle("Yazı"); // Compile Time Error!
}
}
---
🛠️ 3. Jenerik Metotlar (Generic Methods) 🧰
Sadece sınıfın tamamı değil, tek bir metot da jenerik olarak tanımlanabilir. Metot jenerik yapıldığında dönüş tipinden önce `<T>` ifadesi eklenir.
public class Main {
// Farklı tipteki dizilerin elemanlarını ekrana yazdıran jenerik metot
public static <E> void diziYazdir(E[] dizi) {
for (E eleman : dizi) {
System.out.print(eleman + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] sayilar = {1, 2, 3, 4, 5};
String[] isimler = {"Ahmet", "Mehmet", "Ayşe"};
System.out.print("Sayılar *****: ");
diziYazdir(sayilar);
System.out.print("İsimler *****: ");
diziYazdir(isimler);
}
}
---
📐 4. Sınırlandırılmış Tipler (Bounded Type Parameters) 🎯
Bazen jenerik tipin rastgele her tipi kabul etmesini istemeyiz. Örneğin sadece sayısal verilerle işlem yapan bir sınıf tasarlıyorsak tip parametresini kısıtlayabiliriz: `<T extends Number>`
public class SayisalHesaplayici<T extends Number> {
private T sayi;
public SayisalHesaplayici(T sayi) {
this.sayi = sayi;
}
public double kareAl() {
// 'Number' sınıfından türediği garanti olduğu için doubleValue() kullanılabilir
return sayi.doubleValue() * sayi.doubleValue();
}
}
// Kullanımı:
// SayisalHesaplayici<Integer> h1 = new SayisalHesaplayici<>(5); // ✅ Geçerli
// SayisalHesaplayici<Double> h2 = new SayisalHesaplayici<>(4.5); // ✅ Geçerli
// SayisalHesaplayici<String> h3 = new SayisalHesaplayici<>("A"); // ❌ HATA! String, Number değildir!
---
🃏 5. Wildcards (Joker Karakter: `?`) ❓
Jenerik yapılarda bilinmeyen veri tiplerini temsil etmek için **`?` (Joker)** sembolü kullanılır.
1. **Unbounded Wildcard (`List<?>`):** Herhangi bir tipi kabul eder.
2. **Upper Bounded Wildcard (`List<? extends Number>`):** `Number` sınıfı ve onun **alt sınıflarını** kabul eder (Salt okuma senaryolarında idealdir).
3. **Lower Bounded Wildcard (`List<? super Integer>`):** `Integer` sınıfı ve onun **üst sınıflarını** kabul eder.
import java.util.Arrays;
import java.util.List;
public class Main {
// Sadece Number ve alt sınıflarının listelerini kabul eden metot
public static double listeToplaminiHesapla(List<? extends Number> liste) {
double toplam = 0.0;
for (Number n : liste) {
toplam += n.doubleValue();
}
return toplam;
}
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(10, 20, 30);
List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);
System.out.println("Integer Toplam: " + listeToplaminiHesapla(intList));
System.out.println("Double Toplam : " + listeToplaminiHesapla(doubleList));
}
}
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Generics kavramını, tip güvenliğini, Jenerik Sınıf ve Metot tanımlamayı, Bounded Types sınırlamalarını ve Wildcard (`?`) kullanımını öğrendik.
👉 **Bölüm 18'de Bizi Ne Bekliyor?**
• Modern Java Dönüm Noktası: **Lambda Expressions ve Functional Interfaces** ⚡
• Anonim Sınıflar vs Lambda İfadeleri
• `@FunctionalInterface` Anotasyonu
• Hazır Fonksiyonel Arayüzler (`Predicate`, `C
onsumer`, `Supplier`, `Function`)
• Metot Referansları (`System.out:
rintln`)
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! ☕✨
Selamlar! Serimizin 17. bölümüne hoş geldiniz.
Önceki bölümde `try-catch-finally` bloklarını, Checked/Unchecked istisnaları ve özel Custom Exception sınıfları yazmayı görmüştük. Bu bölümde ise kodlarımızda tip güvenliğini (Type Safety) sağlayan, `ClassCastException` hatalarını derleme zamanında engelleyen ve esnek yapılar kurmamıza imkan tanıyan **Generics (Jenerik Yapılar)** konusunu işleyeceğiz.
---
📌 1. Generics Nedir ve Neden İhtiyaç Duyulur? 🛡️
Java 5 öncesinde koleksiyonlar gibi yapılarda her şey `Object` tipinde tutulurdu. Bu durum iki temel soruna yol açıyordu:
1. Her veri okunurken elle tip dönüşümü (Explicit Casting) yapmak gerekiyordu.
2. Hatalı tip atamaları derleme zamanında değil, uygulama çalışırken (`Runtime`) `ClassCastException` hatası veriyordu.
**Generics**; sınıfların, arayüzlerin ve metotların çalışacağı veri tiplerinin parametre olarak belirlenmesini sağlar.
### Generics'in Avantajları:
✨ **Tip Güvenliği (Type Safety):** Hatalı veri tipleri daha derleme aşamasında (`Compile-Time`) tespit edilir.
✨ **Casting İhtiyacının Ortadan Kalkması:** Tür dönüşümü kodlarına gerek kalmaz.
✨ **Kodun Yeniden Kullanılabilirliği:** Farklı veri tipleri için tek bir sınıf veya metot yazılabilir.
---
🏛️ 2. Jenerik Sınıf (Generic Class) Tanımlama ⚙️
Jenerik sınıflar tanımlanırken sınıf isminin yanına elmas operatörü `<T>` eklenir.
Sık Kullanılan Tip Parametre İsimlendirmeleri:
• `T` -> Type (Tip)
• `E` -> Element (Koleksiyon elemanı)
• `K` -> Key (Anahtar)
• `V` -> Value (Değer)
• `N` -> Number (Sayısal Tipler)
### Jenerik Kutusu Sınıfı (`Kutu.java`):
public class Kutu<T> {
private T icerik;
public void ekle(T icerik) {
this.icerik = icerik;
}
public T getIcerik() {
return icerik;
}
}
### Kullanımı (`Main.java`):
public class Main {
public static void main(String[] args) {
// String tipi için Kutu nesnesi
Kutu<String> metinKutusu = new Kutu<>();
metinKutusu.ekle("Java Generics Eğitimi");
String metin = metinKutusu.getIcerik(); // Explicit Cast GEREKMEDİ!
System.out.println("Metin: " + metin);
// Integer tipi için Kutu nesnesi
Kutu<Integer> sayiKutusu = new Kutu<>();
sayiKutusu.ekle(100);
int sayi = sayiKutusu.getIcerik();
System.out.println("Sayı: " + sayi);
// HATA! Derleyici tipi kontrol ettiği için yanlış veri engellenir:
// sayiKutusu.ekle("Yazı"); // Compile Time Error!
}
}
---
🛠️ 3. Jenerik Metotlar (Generic Methods) 🧰
Sadece sınıfın tamamı değil, tek bir metot da jenerik olarak tanımlanabilir. Metot jenerik yapıldığında dönüş tipinden önce `<T>` ifadesi eklenir.
public class Main {
// Farklı tipteki dizilerin elemanlarını ekrana yazdıran jenerik metot
public static <E> void diziYazdir(E[] dizi) {
for (E eleman : dizi) {
System.out.print(eleman + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] sayilar = {1, 2, 3, 4, 5};
String[] isimler = {"Ahmet", "Mehmet", "Ayşe"};
System.out.print("Sayılar *****: ");
diziYazdir(sayilar);
System.out.print("İsimler *****: ");
diziYazdir(isimler);
}
}
---
📐 4. Sınırlandırılmış Tipler (Bounded Type Parameters) 🎯
Bazen jenerik tipin rastgele her tipi kabul etmesini istemeyiz. Örneğin sadece sayısal verilerle işlem yapan bir sınıf tasarlıyorsak tip parametresini kısıtlayabiliriz: `<T extends Number>`
public class SayisalHesaplayici<T extends Number> {
private T sayi;
public SayisalHesaplayici(T sayi) {
this.sayi = sayi;
}
public double kareAl() {
// 'Number' sınıfından türediği garanti olduğu için doubleValue() kullanılabilir
return sayi.doubleValue() * sayi.doubleValue();
}
}
// Kullanımı:
// SayisalHesaplayici<Integer> h1 = new SayisalHesaplayici<>(5); // ✅ Geçerli
// SayisalHesaplayici<Double> h2 = new SayisalHesaplayici<>(4.5); // ✅ Geçerli
// SayisalHesaplayici<String> h3 = new SayisalHesaplayici<>("A"); // ❌ HATA! String, Number değildir!
---
🃏 5. Wildcards (Joker Karakter: `?`) ❓
Jenerik yapılarda bilinmeyen veri tiplerini temsil etmek için **`?` (Joker)** sembolü kullanılır.
1. **Unbounded Wildcard (`List<?>`):** Herhangi bir tipi kabul eder.
2. **Upper Bounded Wildcard (`List<? extends Number>`):** `Number` sınıfı ve onun **alt sınıflarını** kabul eder (Salt okuma senaryolarında idealdir).
3. **Lower Bounded Wildcard (`List<? super Integer>`):** `Integer` sınıfı ve onun **üst sınıflarını** kabul eder.
import java.util.Arrays;
import java.util.List;
public class Main {
// Sadece Number ve alt sınıflarının listelerini kabul eden metot
public static double listeToplaminiHesapla(List<? extends Number> liste) {
double toplam = 0.0;
for (Number n : liste) {
toplam += n.doubleValue();
}
return toplam;
}
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(10, 20, 30);
List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);
System.out.println("Integer Toplam: " + listeToplaminiHesapla(intList));
System.out.println("Double Toplam : " + listeToplaminiHesapla(doubleList));
}
}
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Generics kavramını, tip güvenliğini, Jenerik Sınıf ve Metot tanımlamayı, Bounded Types sınırlamalarını ve Wildcard (`?`) kullanımını öğrendik.
👉 **Bölüm 18'de Bizi Ne Bekliyor?**
• Modern Java Dönüm Noktası: **Lambda Expressions ve Functional Interfaces** ⚡
• Anonim Sınıflar vs Lambda İfadeleri
• `@FunctionalInterface` Anotasyonu
• Hazır Fonksiyonel Arayüzler (`Predicate`, `C
onsumer`, `Supplier`, `Function`)
• Metot Referansları (`System.out:
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! ☕✨
🔒 Bu içeriği görmek için giriş yapın