Pure Java – 76 Generics & Collections – Generics – 01

Merhaba Arkadaslar,
Bu bolumde Generics konusundan bahsedecegim. Onceki bolumlerde Generics yapisini kullandik fakat burada isin biraz daha detayina girmeye calisacagiz.

Generics yapisi, type kavramini class ve interfaceler icin aktif eder. Class, interface veya method taniminda(define/declare) parametre ile bu tip bilgisini kullanabilmemizi saglar. Peki bunun en onemli faydasi nedir ?  type parametreleri kodunuza tekrar kullanilabilirlik ozelligi kazandiririr. Bu kismi ilerleyen yazilarda inceleyecegiz.

Generics yapisinin non-generics yapisina karsi su avantajlari vardir;

  • Compile time/derleme zamaninda guclu bir type check/tip kontrolu.
  • Cast etme islemini ortadan kaldirmasi
    Ornegin non-generics olarak tanimli bir AraryList’ten elemani get ile aldigimizda geriye Object doner.Non-generics Collection’larda elemanlar java.lang.Object tipindedir.
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast
  • Generic/genelleyici bir implementation
    Generics yapisini kullanarak farkli type degerine sahip Collection’lar icin kullanilabilecek, customized ozellige sahip , type safe ve kolay okunabilir bir kod yazilabilir.

Mix Generics & Non-Generics Collection

Java’da array/diziler her zaman type safe’tir. String olarak tanimlanmis bir dizi bir baska tipte eleman eklenemez. Java 5 ten once type safe Collection tanimlanmasi icin bir yapi mevcut degildi. Java 5 ten sonra  Collection yapilari icin Generics yapisi eklendi.

Bir non-generic collection herhangi bir tipte elaman tutabilir. Unutmayalim bir collection’in elemanlari primitive olamaz her zaman objedir.

Non-generics ve generics tanimli oldugu durumu hatirlamak icin bir ornek yapalim ;

import java.util.ArrayList;
import java.util.List;

class Dog {
}

public class Test {

	public static void main(String[] args) {
		List myList = new ArrayList();

		myList.add("test");
		myList.add(10);
		myList.add(new Dog());

		String str = (String) myList.get(0);
		// non-generics bir collection yapisinda elemani aldiktan sonra cast
		// etmemiz gerekir.

		List <String> myGenericsList = new ArrayList <String>();

		myGenericsList.add("test");
		// myGenericsList.add(10);
		//  olarak generics yapida tanimladigimiz icin farkli tipte bir
		// eleman ekleyemeyiz.

	}
}

Non-generics ve generics yapisini beraber kullandigimizda risk soz konusudur. Generics yapida tanimli bir List’i non-generics tanimli bir parametre alan metoda arguman olarak verebiliriz. Eger ilgili metotta farkli tipte bir eleman eklersek bu durumda ekledigimiz noktada hata almayiz. Sonrasinda elemanlara ulasirken hata aliriz.

import java.util.ArrayList;
import java.util.List;

public class TestLegacy {

	public static void main(String[] args) {
		List<Integer> myList = new ArrayList<Integer>();
		myList.add(10);
		myList.add(20);

		addSomeElements(myList);

		// myList generics yapisinda tanimlandigi icin get metodu Integer
		// tipinde doner.
		// Fakat bu eleman "danger" olarak diger metotta eklendi. 3.indexteki
		// elemana ulasirsak exception aliriz ;
		// java.lang.ClassCastException:
		Integer exception = myList.get(3);

		// for (Integer i : myList) {
		// System.out.println(i);
		// // 3.indexe geldiginde calisma zamaninda hata olacaktir.
		// // java.lang.ClassCastException:
		// }

	}

	// Generics tanimli bir List i non-generics tanimli bir parametre alan
	// metoda arguman olarak verebiliriz.

	public static void addSomeElements(List nonGenericList) {
		nonGenericList.add(30);

		nonGenericList.add("danger!");
		// List'e yeni bir eleman ekledik. Bu noktada calisma zamani hatasi
		// vermeyecektir!
	}
}

Burada aklimiza su soru gelebilir , neden generics yapisinda bir List’e farkli bir tipte eleman eklenebiliyor ve eklendigi noktada problem cikarmiyor. Bunun nedeni type bilgisi calisma zamaninda yoktur. Bunun anlami tum generics tanimlamalar calisma zamaninda compiler tarafindan silinir.

List<Integer> myList = new ArrayList<Integer>();
// List myList = new ArrayList();
//calisma zamaninda generics tanimlari silinir bu sekle donusturulur.

Generics yapisi compile-time koruma saglar. Bu sayede derleme zamaninda generics tanimindan farkli bir tipte eleman eklemenize izin vermez.

Dizileri/array dusundugumzde , diziler hem derleme zamaninda/compile time hem de calisma zamaninda /runtime koruma saglarlar. Peki neden generics yapisi da bu sekilde hem calisma zamaninda/runtime hem derleme zamaninda/compile time koruma saglamaz. Bunun nedeni legacy/eski kodlara destek saglamaktir.

Bununla birlikte eger non-generics ve generics tanimlarini birbiriyle mix etmezsek runtime icin korumaya gerek yoktur, generics ifadesinin bizim icin compile time da koruma saglamasi yeterli olacaktir.

Polymorphism & Generics
Onceki bolumlerde polymorphism konusunu incelemistik. Hatirlayacagimiz gibi IS-A kuralina uygun sekilde bir referans degisken kendi tipinde ya da subclass/altsinif tipinde bir objeye referansta bulunabilir. Peki generics ifadeler icin de bu sekilde kullanilabilir mi ?

import java.util.ArrayList;
import java.util.List;

class Animal {

}

class Dog extends Animal {

}

public class PolymorphismTest {

	public static void main(String[] args) {
		List<Animal> animalList = new ArrayList<Animal>();
		List<Dog> dogList = new ArrayList<Dog>();
		// ArrayList IS-A List bu nedenle List tipinde bir referans degisken
		// ArrayList tipinde bir objeyi referansta bulunabilir.

		// List <Animal> animalDogList = new ArrayList <Dog>();
		// derleme hatasi verecektir.

		// Referans degiskenin taniminda kullandigimiz generics tanimi ile ,
		// obje olustururken kullandigimiz generics ifadesi ayni olmalidir.
		// Subclass dahi olacak sekilde farkli olamaz.
	}
}

Collection taniminda, referans degiskenin taniminda kullandigimiz generics ifadesi ile new anahtar kelimesi ile kullandigimiz generics ifadesi ayni olmalidir. Buraya polymorphismde oldugu gibi subclass tipi bile yazamayiz!

Peki array tanimlarinda durum nasil olmaktadir ?

class Animal {

}

class Dog extends Animal {

}

public class PolymorhismTestArray {

	public static void main(String[] args) {
		Animal[] animalArray = new Animal[10];
		Dog[] dogArray = new Dog[10];
		Animal[] animalDogArray = new Dog[10];
	}
}

Array/diziler icin bu durum problem cikarmayacaktir. IS-A kuralina uygun sekilde dizi tanimlamasi yapilabilir.

List <Animal> animalDogList = new ArrayList <Dog>(); 
//derleme hatasi verir
Animal[] animalDogArray = new Dog[10];
//derleme hatasi vermez!

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *