Generics'e Giriş
Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 53 / 87.
Bir değer saklayan ve bu değeri daha sonra geri getiren bir sınıf oluşturmanız gerektiğini hayal edin. Generic'ler olmadan, her tür için ayrı sınıflar yazmanız gerekirdi; biri Integer için, biri String için, biri Double için vb. Bu durum kod tekrarına ve bakım zorluklarına yol açar.
Generic'ler, tip güvenliğini korurken herhangi bir tiple çalışan sınıflar ve metotlar yazmanıza olanak tanıyarak bu sorunu çözer. Sınıfı kullandığınızda gerçek bir tiple değiştirilen bir yer tutucu (tip parametresi olarak adlandırılır) tanımlarsınız:
// Generic'ler olmadan - Object kullanır, tür dönüştürme gerektirir
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // Manuel tür dönüştürme gerekli
// Generic'ler ile - tip güvenli, tür dönüştürme yok
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0); // Tür dönüştürme gerekmezAçılı ayraçlar <T> bir tip parametresini belirtir. List<String> yazdığınızda, derleyiciye bu listenin yalnızca dizeler içereceğini söylersiniz. Eğer bir tam sayı eklemeye çalışırsanız, derleyici hatayı çalışma zamanında başarısız olmak yerine hemen yakalar.
Generikler iki temel avantaj sağlar: açık tür dönüşümü (explicit casting) ihtiyacını ortadan kaldırırlar ve tür hatalarını çalışma zamanı yerine derleme zamanında yakalarlar. Bu, kodunuzu hem daha güvenli hem de daha temiz hale getirir. İlerleyen derslerde, kendi generic sınıflarınızı ve metotlarınızı nasıl oluşturacağınızı keşfedeceğiz.
Görev
KolayEski yöntemi (tür dönüşümü ile Object kullanarak) yeni yöntemle (tür güvenliği ile generic kullanarak) karşılaştırarak generic yapısının gücünü gösteren basit bir depolama sistemi oluşturalım.
Aradaki farkı bizzat görmek için üç dosya oluşturacaksınız:
OldBox.java: Değerleri generic öncesi yöntemle saklayan bir sınıf oluşturun. OldBox sınıfınızObjecttüründe özel (private) bircontentalanına sahip olmalıdır. Bir Object kabul eden ve onu saklayan bir yapıcı (constructor) ile Object döndüren birgetContent()metodu ekleyin. Bu yaklaşım çalışır ancak değerleri alırken tür dönüşümü (casting) gerektirir.GenericBox.java: Şimdi generic kullanarak modern ve tür güvenli sürümü oluşturun. GenericBox sınıfınız, bildiriminde birTtür parametresi kullanmalıdır.Ttüründe özel bircontentalanına, birTdeğeri kabul eden bir yapıcıya veTtürünü döndüren birgetContent()metoduna ihtiyaç duyar. Bu sınıfı kullanırken tür dönüşümüne gerek yoktur!Main.java: Her iki yaklaşımı yan yana gösterin. İki girdi alacaksınız: bir kelime (String) ve bir sayı (integer).Önce eski yaklaşımı kullanın: kelimeyi saklayan bir OldBox oluşturun, ardından onu String türüne dönüştürerek geri alın ve şunu yazdırın:
OldBox (with cast): [value]Ardından generic yaklaşımı kullanın: aynı kelimeyi saklayan bir
GenericBox<String>oluşturun, tür dönüşümü yapmadan geri alın ve şunu yazdırın:GenericBox (no cast): [value]Sonra generic yapısının tam sayılarla çalışmasını gösterin: sayıyı saklayan bir
GenericBox<Integer>oluşturun, onu geri alın ve şunu yazdırın:GenericBox Integer: [value]Son olarak, boş bir satır ve ardından şunu yazdırın:
Type safety: Generics catch errors at compile time!
Sırasıyla iki girdi alacaksınız: bir kelime (String) ve bir sayı (String olarak gelen ve sizin ayrıştıracağınız integer).
Temel farka dikkat edin: OldBox ile (String) box.getContent() şeklinde tür dönüşümü yapmalı ve türü doğru tahmin ettiğinizi ummalısınız. GenericBox ile derleyici türü bilir ve tür dönüşümüne gerek kalmaz. Generic yapısının temel faydası budur—tür dönüşümü zahmeti olmadan tür güvenliği!
Kopya kağıdı
Generic yapılar, tip güvenliğini korurken herhangi bir tiple çalışan sınıflar ve metotlar yazmanıza olanak tanır. Sınıf kullanıldığında gerçek tiplerle değiştirilen tip parametrelerini (yer tutucuları) kullanırlar.
Generic yapılar olmadan (Object kullanarak):
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // Manuel tür dönüşümü (casting) gerekirGeneric yapılar ile (tip güvenli):
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0); // Tür dönüşümüne gerek yokGeneric bir sınıf oluşturma:
public class GenericBox<T> {
private T content;
public GenericBox(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}Generic bir sınıfı kullanma:
GenericBox<String> stringBox = new GenericBox<String>("Hello");
String value = stringBox.getContent(); // Tür dönüşümü yok
GenericBox<Integer> intBox = new GenericBox<Integer>(42);
Integer number = intBox.getContent(); // Tip güvenliAçılı ayraçlar <T> bir tip parametresini belirtir. Avantajları şunlardır: açıkça tür dönüşümü yapmaya gerek kalmaz ve tip hataları çalışma zamanı yerine derleme zamanında yakalanır.
Kendin dene
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String word = scanner.nextLine();
int number = Integer.parseInt(scanner.nextLine());
// TODO: word saklayan bir OldBox oluşturun
// String türüne dönüştürerek (cast) geri alın ve yazdırın: "OldBox (with cast): [value]"
// TODO: word saklayan bir GenericBox<String> oluşturun
// Tür dönüşümü (cast) yapmadan geri alın ve yazdırın: "GenericBox (no cast): [value]"
// TODO: number saklayan bir GenericBox<Integer> oluşturun
// Geri alın ve yazdırın: "GenericBox Integer: [value]"
// TODO: Boş bir satır yazdırın, ardından şunu yazdırın:
// "Type safety: Generics catch errors at compile time!"
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarAlanlar (Öznitelikler)Yapıcı MetotYapıcı Metot Aşırı YüklemeÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (extends)super Anahtar KelimesiMetot Geçersiz Kılma (@Override)Yapıcı Metot ZincirlemeObject SınıfıTekli ve Çok Seviyeli KalıtımNeden Çoklu Sınıf Kalıtımı Yok?Özet - Çalışan Hiyerarşisi7Özel Metotlar ve Object Sınıfı
toString() Metoduequals() ve hashCode()clone() MetoducompareTo() ve ComparableComparator ArayüzüÖzet - Özel Sıralama2Erişim Belirleyiciler ve Kapsülleme
Erişim Seviyelerine Genel BakışGetter ve Setter MetotlarıBilgi Gizlemefinal Anahtar KelimesiÖzet - Banka Hesabı Yöneticisi5Polimorfizm
Metot Aşırı Yükleme TemelleriMetot Geçersiz Kılma (Çalışma Zamanı)Upcasting ve Downcastinginstanceof OperatörüSoyut Sınıflar ve MetotlarÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımAgregasyon vs KompozisyonDahili, Yuvalanmış ve Anonim SınıflarEnum'lar ve Enum MetotlarıRecords (Java 16+)Sealed Classes (Java 17+)11Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıBuilder KalıbıObserver KalıbıStrategy Kalıbı14Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi3Sınıf Özellikleri ve Statik Üyeler
Instance ve Statik DeğişkenlerStatik MetotlarStatik BloklarSabitler (static final)Özet - Sayaç ve Utility6Arayüzler ve Soyut Sınıflar
Arayüzlere GirişArayüzleri UygulamaÇoklu Arayüz UygulamaArayüzlerde Default ve StaticSoyut Sınıflar ve ArayüzlerFonksiyonel ArayüzlerÖzet - Ödeme Sistemi9Generics
Generics'e GirişGeneric SınıflarGeneric MetotlarSınırlandırılmış Tip ParametreleriWildcard'lar (?, extends, super)Özet - Generic Container12Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıYineleyici Kalıbı