İlginizi Çekebilir
Java Generics Nedir?
  1. Ana Sayfa
  2. Java
  3. Java Generic Nedir?
Trendlerdeki Yazı

Java Generic Nedir?

Bugün bu yazı içeriğinde koleksiyon yapılarının devamı olacak şekilde java generic nedir sorusuna cevap ararken sizlere sağlamış olduğu bazı avantajlardan bahsedeceğim.

Java generic kavramı programlarımıza işlevsellik ve bazı avantajlar sağlıyor olsada konu genişliği ve karmaşık bir yapıda olmasından dolayı, çoğu kişi tarafından ilgi çekici bulunmayabilir ama ben sizler için alt başlıklarda en sade anlatım yapısı ve anlatımını gerçekleştirdiğim kavramın örnek kodları ile görsellendirerek akılda kalıcılığı arttırmayı ve ilginizi çekmeyi hedefliyorum. 👀

Java Generic Nedir?

Konuyu temelden ele alacak olursak Java’da her oluşturduğumuz sınıf yapısı Object sınıfından türeyen alt sınıflardır. Bu yüzden oluşturduğumuz her bir nesne Object tipine ait nesnelerdir.

Bu özelliğinden dolayı oluşturduğumuz bu nesneleri her veri tanımlaması içerisinde kullanabiliriz. Tanımladığımız bu yapılar program derlenirken bir hata vermez fakat run-time esnasında programımız, tanımlı verilerin aynı tipte olmadığını tespit ederek bizlere hata göstermesi olası bir hale gelir. Bu sorunu çözmek içinde kullanacağımız kurtarıcı kavram Generic yapılardır.

Uzun lafın kısası, Java Generic, programlarımız içerisinde farklı referans veri tiplerine ev sahipliği yapacak işlemlerimize, üzerinde hangi referans tiplerini taşımasını istediğimize karar vermemize olanak sağlayan bir sınıftır.

Teorik bilgi olarak her şey yolunda, anlaşılır olarak gözükmeyebilir ama kullanım yapısını ele alırsak java generic nedir sorusu için aklımızda bazı şeylerin canlanabileceğini düşünüyorum.

Java Generic Tanımlama

Java Collections Nedir? konu içerisinde bahsetmiş olduğum non-generic ve generic tanımlama işlemini List yapısını ele alarak basit bir şekilde tanımlama örneğini şu şekilde verebilirim:

//---> Generic Tanımlama İşlemi <--- \\
List nonGenericList = new ArrayList(); // --> Non-Generic Tanımlaması.
List<String> genericList = new ArrayList<>(); // --> Generic Tanımlaması.
nonGenericList.add("String Bir Değer Atıyorum.");
nonGenericList.add(100+" İstersem Integer Bir Değer, "+15.5+" İstersem Double Bir Değer Atıyabiliyorum.");
genericList.add("Sadece String Bir Değer Atıyorum."); //--> Veri tipini belirttiğim için sadece o veri tipinde ekleme yapabiliyorum.
genericList.add("<veriTipi> Yapısına Elmas'da Deniliyor.");
//---> Ekrana Yazdırma <--- \\
System.out.println("----------------\n< Non-Generic Tanımlamalar >\n----------------\n-> "+nonGenericList.get(0) +"\n-> "+nonGenericList.get(1));
System.out.println("----------------\n< Generic Tanımlamalar >\n----------------\n-> "+genericList.get(0) +"\n-> "+genericList.get(1)+"\n----------------");

Kod Çıktısı:

Java Generics Nedir?
Java Generic ve Non Generic Tanımlama

Generic yapımızı belirttiğimiz < ve > işareti literatür içerisinde diamond 💎 olarak geçer ve bu kavram arasında belirttiğimiz veri tipleri ile işlemlerimizi, sınıflarımızı generic bir yapı haline getirmiş oluruz.

Java Generic Avantajları ve Neden Kullanmalıyız?

Generic kavram hakkında bazı şeyler anlattık iyi hoş ama biz bunu neden kullanmalıyız gibi önemli bir soruya henüz cevap vermediğimin farkındayım.

Bir çok dilin aksine Java, tip güvenliği (type safety) olan bir dildir. Yani bir veri tanımlaması yapmak istediğimiz zaman hangi türde bir değer tanımlaması yaptığımızı belirtmek zorundayız. Programımız bu atamaları derleme esnasında kontrol ederek yanlış bir atama durumunda bizlere bu konuyu bildirerek bir exception fırlatır.

Bu sorunu, non-generic bir tanımlama tip ihlali yapıp yapmadığımızı kontrol edilmez bir hale getirdiği için derleme esnasında değil programın çalışma esnasında hatalar ile karşılaşabiliriz. Bu durumda hatanın kaynağını erken keşfetmekten daha ötede zorlaştırıcı bir yapı içerisinde kendimizi saç baş yolarken bulmamız kaçınılmaz bir hale gelir. 🤔

Bu sorun ile karşılaşmamak için programlarımızın içerisinde java generic tanımlama yaparak işlemlerimizdeki hataları minimuma indirebilir ve Runtime sırasında ortaya çıkacak ClassCastException hatalarını programımızın derlenme esnasında yakalayabiliriz.

İki kullanım şekli içinde örnek kod dizisi oluşturarak ekran çıktısına bakacak olursak aşağıdaki gibi bir tanımlama işimizi görecektir.

Hatalı Tanımlama:

//---> Non-Generic Tanımlama İşlemi <---\\
List listExceptionExample = new ArrayList();
listExceptionExample.add("Buraya String Bir Metin Ekleyelim.");
listExceptionExample.add(05042021); //---> Integer türünde bir veri daha ekledik.

System.out.println("----------------\n<Class Cast Exception Hatası>");
for(int i=0; i<listExceptionExample.size();i++){
try{
String value = (String) listExceptionExample.get(i);
System.out.println("----------------\n-> "+value +"\n----------------");
}
catch (ClassCastException e){
System.out.println("-> Class Cast Excepiton Hatası Aldım.  -> Hata Hash Kodu: "+e.hashCode()+"\n----------------");
}
}

Kod Çıktısı:

Java Non-Generic ClassCastException Hatası
Java Non-Generic Tanımlamada Karşılaşacağımız Hata Yapısı

Non-generic bir tanımlama yaptığımız zaman programımız çalışma esnasında hata verirken bu durumda bizi karmaşık ve hatanın kaynağını bulma konusunda çeşitli zorluklar ile karşılaşmamıza imkan verebilir. Bu yüzden bu sorunu daha önceden keşfetmek ve önlem alabilmek için aynı kodu generic bir yapı halinde oluşturursak kod çıktımız aşağıdaki gibi olacaktır.

Doğru Tanımlama:

//---> Generic Tanımlama İşlemi <---\\
List <String> listGenericExample = new ArrayList<>();
listGenericExample.add("String Bir Tanımlama İşlemi Gerçekleştiriyorum.");
listGenericExample.add(100); //--> Kullandığımız ide zaten bir hata yaptığımızı bize bu esnada gösterecektir.

System.out.println("----------------\n<Generic Yapıda Derleme Aşaması>\n----------------");
for(int i=0;i<listGenericExample.size();i++)
System.out.println("-> "+listGenericExample.get(i)+"\n----------------");

Kod Çıktısı:

Java Generic Tanımlama Hatası
Java Generic Tanımlamada Karşılaşacağımız Hata Yapısı

Aynı yapı şeklinde tanımlama yaptığımıza rağmen generic yapı kullandığımız için programın derlenme esnasında hatamızı bize göstererek sorunu çözmemizi ister. Bu durumda bize hatamızın kaynağını daha kolay fark etmemize imkan sağladığı için zaman kazandırır.

Generic yapıları tanımlarken belirttiğimiz veri tiplerinin yanında bazı harf atamaları da gerçekleştirebiliriz. Bu harf yapıları çeşitli anlamları ve açıklamaları bulunmaktadır.

Java Generics İsimlendirme Standartları
Java Generic İsimlendirme Standartları

Şu zamana kadar konu işlerken hep olarak bir tanımlama yapmamıza rağmen yukarıda yer alan ifadeleri de kullanabiliriz. Bu ifadelerin dışında çeşitli tanımlamalarda gerçekleştirebiliriz faka bu tablo üzerinde yer alan ifadeler java isimlendirme standartlarında yer alan ifadelerdir.

Bu ifade yapılarını kullanarak basit bir tanımlama işlemini aşağıdaki aşamaları izleyerek gerçekleştirelim.

#1 Öncelikle liste yapısında çeşitli değerler tutabilmek için ListManager isminde bir sınıf oluşturarak içerisinde çeşitli veri yapılarında veriler tutabilmek için gerekli tanımlamaları gerçekleştiriyorum.

import java.util.ArrayList;

public class ListManager <T> {
    private ArrayList<T> list = new ArrayList<>();

    public void addList(T element){
        this.list.add(element);
    }
    public ArrayList<T> getList(){
        return this.list;
    }
}

#2 Yapmış olduğum tanımlamanın mantığını kavrayabilmek, generic yapının mantığını anlamak için Main sınıfı içerisinde öğrenci bilgilerini kayıt altına alacağım basit bir tanımlama gerçekleştirerek for döngüsü ile tanımladığım verileri ekrana yazdırtıyorum.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ListManager<Integer> studentNo = new ListManager<>();
        studentNo.addList(203006001);
        studentNo.addList(203006014);
        studentNo.addList(203006034);
        ListManager<String> studentName = new ListManager<>();
        studentName.addList("Yasin");
        studentName.addList("Rüzgar");
        studentName.addList("Metehan");

        ArrayList<Integer> schoolNo =  studentNo.getList();
        ArrayList<String> studentInfo = studentName.getList();

        for(int i=0;i<studentInfo.size();i++){
            System.out.println("----------------\n< "+(i+1)+". Öğrenci Bilgisi >\n----------------\n-> Öğrenci Numarası: "+schoolNo.get(i)+"\n-> Öğrenci İsmi: "+studentInfo.get(i));
        }
        System.out.println("----------------");
    }
}

Kod Çıktısı:

Java Generic Yapılarda İsimlendirme
Java Generic İsimlendirme Kullanımı

Bazı işlemlerimizde generic yapılarımıza sonradan veri ataması yapacak olabiliriz ve bunu o işlem anında belirlemek istediğimiz durumlarda yukarıda olduğu gibi basit bir isimlendirme yapısı kullanabiliriz. Tabi, bu kullanmış olduğumuz isimlendirme yapısı haricinde farklı atamalar gerçekleştirerek de aynı sonuca ulaşabiliriz.

Bu tanıma örnek olarak bir iş kayıt sisteminin yapılacağı ve maaş bilgilerinin bazı durumlarda integer bazı durumlarda ise double olarak tutulması istenilebilir. Bu istek karşısında nasıl bir tanımlama yapmamız gerekeceğini ele alarak basit bir örnek oluşturalım. Bu örnek kod dizisini oluştururken uyguladığım aşamalar şu şekildedir:

#1 Çalışanların genel olarak bilgilerini tutacağım EmployeManager isminde generic bir sınıf tanımlaması gerçekleştirerek çalışanların çeşitli bilgilerini tutacağım bir tanımlama gerçekleştirdim.

public class EmployeManager <benimÖzelTipim>{
    private final String sirketKisaltmasi = "COMP";
    benimÖzelTipim maas;
    private String kayitNumarasi;
    String isim, soyisim;

    public String getKayitNumarasi(){
        int i = isim.length()/2+1;
        int v = soyisim.length()/2;
        this.kayitNumarasi = sirketKisaltmasi+"-"+isim.substring(i)+soyisim.substring(v);
        return kayitNumarasi.toUpperCase();
    }
}

#2 Yapmış olduğum tanımlamaya veri eklemek için Main sınıfına giderek oluşturmuş olduğum sınıfı nesneye çevirerek verilerin eklenmesini gerçekleştirdim ve verilerin ekran çıktılarını aldım.

public class Main {
    public static void main(String[] args) {
        //---> Çalışan Ekleme İşlemi <---\\
        EmployeManager<Integer> calisan = new EmployeManager<>();
        calisan.isim = "Mustafa Enes";
        calisan.soyisim = "Barut";
        calisan.maas = 5000;
        EmployeManager<Double> muhendis = new EmployeManager<>();
        muhendis.isim ="Metehan";
        muhendis.soyisim = "Durmuş";
        muhendis.maas = 8575.50;

        System.out.println("----------------\n< Çalışan Bilgileri >\n----------------\n-> Çalışanın İsmi: "+calisan.isim+"\n-> Çalışanın Soyismi: "+calisan.soyisim+"\n-> Maaşı: "+calisan.maas+"\n-> Kayıt Numarası: "+calisan.getKayitNumarasi());
        System.out.println("----------------\n< Mühendis Bilgileri >\n----------------\n-> Mühendis İsmi: "+muhendis.isim+"\n-> Mühendis Soyismi: "+muhendis.soyisim+"\n-> Maaşı: "+muhendis.maas+"\n-> Kayıt Numarası: "+muhendis.getKayitNumarasi()+"\n----------------");
    }
}

Kod Çıktısı:

Java Generic Nedir
Java Generic Örneği

Evet, Java generic nedir sorusuna, en sade ve anlaşılır şekilde bir tanımlama gerçekleştirdiğimi düşünüyorum. Bu konuda bulunan pek çok kaynağı araştırdığım zaman örneklerin azlığı ve teorik bilgilerin fazla karışık verilmesinden dolayı, benim gibi Java’yı öğrenmeye yeni başlayan kişilere bu tür konu anlatımları ağır gelebiliyor.

Bunun farkında olduğum için elimden geldiğince konu anlatımını örneklendirerek ve anlatımları kodlara dökerek göstermemin birazda olsa daha faydalı ve aklımızda canlandırma yetisini harekete geçirdiğini düşünüyorum. Eğer sizin bu konu işleyişi hakkında farklı bir öneriniz, yorumunuz yada java generic nedir konusu ile alakalı aklınıza takılan bir soru var ise aşağıda bulunan yorum yap 💬 kısmından benimle iletişime geçebileceğiniz gibi burada 👁‍🗨 bulunan Oracle tarafından hazırlanmış kaynağa da göz atabilirsiniz .

Yorum Yap

Yazar Hakkında

Yazmayı, öğrenmeyi, öğrendiklerini paylaşmayı , kodlamayı ve günün birinde Yönetim Bilişim Sistemleri Uzmanı olmanın hayalini kuran birisiyim.

Yorum Yap