Java 1.5 ve Genel Tipler (Generics)

CorsaiR

Emektar
27 Ara 2005
1,228
18
Çekirdekten
Java 1.5 ile gelen Genel Tipler'i (Generic Types) uygulama geliştirirken ne kadar kullanıyoruz? Eğer sadece listelerden tip dönüşümünü yapmadan nesne çekmek için kullanıyorsak... Bu yazı ile hangi amaçlarda ve ne şekilde kullanıldıklarını inceleyelim.N

edir bu genel tipler (Generics)? Beynimizi çok yormaya gerek yok. Java 1.5 öncesinde bir liste oluşturduğumuzda ve bu listeden bir nesne almak istediğimizde zahmetli bir işe kalkışırdık :

1: List liste = new ArrayList();
2: liste.add(new Integer(0));
3: liste.add(new Integer(1));
4: for(int i=0; i<liste.size(); i++){
5: Integer sayi = (Integer) liste.get(i);
6: }

6. satırda olduğu gibi istediğimiz tipe dönüşüm yaparak (upcasting / downcasting) istediğimiz nesneyi kullanabilirdik.


1: List liste = new ArrayList();
2: liste.add(new Integer(0));
3: liste.add(new Integer(1));
4: liste.add(new String("test"));
5: for(int i=0; i<liste.size(); i++){
6: Integer sayi = (Integer) liste.get(i);
7: System.out.println("["+i+ = "+ sayi);
8: }

Sonuç:

[0] = 0
[1] = 1

Exception in thread "main" java.lang.ClassCastException: java.lang.String
at com.articles.generics.objectcaching.ObjectPoolManager.main(ObjectPoolManager.java:67)

Oluşturduğumuz liste nin sadece Integer tipindeki nesneleri içereceğini düşünürken takım arkadaşımız başka bir yordam içerisinde öyle bir kod yazmışki bu liste içerisine String tipinde bir nesne atmış ( 4. satır ). Çalışma zamanında (Runtime) bu liste içerisindeki nesneleri Integer tipine dönüştürerek alırken String tipinde bir nesnenin gelmesi hata fırlamasına ve uygulamamızın durmasına neden olmaktadır.

Java 1.5 ile gelen genel tipler ( Generics ) bize tam burada yardımımıza koşmaktadır : çok sık kullandığımız Collection ve Map hiyerarşisindeki torbaların (containers) kullanımında yukarıdaki sorunların ortadan kalkması...

1: List<Integer> intList = new ArrayList<Integer>();
2: intList.add(new Integer(1));
3: intList.add(new Integer(2));
4: intList.add(new String("3"));


Satırları javac ile derlemeye çalıştığımızda :

5960_image002.jpg



şeklinde derleme uyarısı alırız. Çünkü 1. satırda <Integer> ifadesi (tip parametresi) ile oluşturacağımız listeye Integer tipi üzerinde işlem gerçekleştireceğimizi söyleriz. String tipinde bir nesneyi listeye koymak istediğimizde ise derleme hatası alırız. Böylece çalışma zamanında (Runtime) beklenmedik tip dönüşümlerinden meydana gelen hatalardan kurtulmuş oluruz.

Nesne Havuzu ( Object Pool )



Jenerik yapıları anlamak için gelin bir uygulama geliştirelim. Bu uygulama veritabanı bağlantı havuzu (DB Connection Pool) yada iş parçacıkları havuzu (Thread Pooling) gibi asıl amacı sürekli tekrarlayan işlemlerde belli bir tipteki nesnelerin her seferde oluşturulması ve silinmesini engellemektir. Böylece uygulamada gereksiz yavaşlamaları engelleyebilir ve nesne takibini iyileştirebiliriz.

Gelin öncelikle uygulamamızı süper yapıları tanımlayarak başlayalım. Bu süper yapılar : arayüzler (interface), süper sınıflar (super class) ve soyut sınıflar (abstract class) olabilir.
Süper yapılara üzerinden uygulamamızı geliştirdiğimiz zaman ileriye yönelik geliştirme ve sistemler arası iletişim daha kolay yapılmış olacaktır.

Oluşturacağımız süper yapılar:

1. Yedeklenebilir Arayüzü (Interface) : Sistem tarafından havuzda tutalacak olan nesnelerin sınıf tanımlamaları bu arayüzü gerçekleştirmelidir.

2. Havuz Arayüzü (Interface) : doldur(), cek()/koy(), bos() soyut yordamlarını içeren arayüzdür. Bu arayüzü gerçekleştiren sınıflar <<Yedeklenebilir>> arayüzünü gerçekleştirmiş yapılar için sınırlandırılmalıdır.

3. HavuzYöneticisi Arayüzü (Interface) : nesneCek(), nesneKoy() ve havuzuKontrolEt() yordamlarını içermektedir.

a. nesneCek() yordamı istenen nesnenin tipine göre ilgili havuzdan nesne çekecek
b. nesneKoy() yordami gönderilen nesneyi, nesnenin tipine göre ilgili havuza geri koyar.
c. havuzuKontrolEt() yordami nesneCek() yordami çağrıldığında ilgili nesne için havuz nesnesinin yaratılıp içerisinin doldurulmasını kontrol eder.

5960_image003.jpg


Havuz Arayüzü



/**
* {@link Yedeklenebilir} arayüzünü gerçekleştirmiş
* nesneler için havuz görevini görür.
*
* @param <T extends YedeklenebilirNesne>
*/
public interface Havuz <T extends Yedeklenebilir> {

/**
* Havuzdan nesne çeker.
* @return T
*/
T cek();

/**
* Nesneyi geri koyar.
* @param object
*/
**** koy(T nesne);

/**
* clazz tipinde nesneleri yaratip kendisini doldurur.
* @param clazz
* @throws NesneYaratmaHatasi
*/
**** doldur(Class<T> clazz) throws NesneYaratmaHatasi;

/**
* clazz tipinde nesnelerden belirtilen adet kadar
* yaratip kendisini doldurur.
* @param clazz
* @param adet
* @throws NesneYaratmaHatasi
*/
**** doldur(Class<T> clazz, int adet) throws NesneYaratmaHatasi;

/**
* Havuzun bos olup olmadigi kontrol edilir
* @return boolean
*/
boolean bos();

}

Havuz arayüzüne ait yukarıdaki tanımlamada dikkatimizi <T extends Yedeklenebilir> tip parametresi çekmektedir. Böylece Havuz arayüzünü sadece Yedeklenebilir arayüzüne erişmiş yapılar için genelleştirmiş / sınırlandırmış (bounding) olduk.

NesneHavuzu Sınıfı



public class NesneHavuzu<T extends Yedeklenebilir>
implements Havuz<T> {

private Vector<T> havuz = new Vector<T>();

/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#doldur(java.lang.Class)
*/
public **** doldur(Class<T> clazz) throws NesneYaratmaHatasi {
this.doldur(clazz, 5);
}

/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#doldur(java.lang.Class, int)
*/
public **** doldur(Class<T> clazz, int adet)
throws NesneYaratmaHatasi {

try {
for(int sayac=0; sayac<adet; sayac++){
this.havuz.add(clazz.newInstance());
}
} catch (InstantiationException e) {
NesneYaratmaHatasi ex =
new NesneYaratmaHatasi(clazz, e.getStackTrace());
throw ex;
} catch (IllegalAccessException e) {
NesneYaratmaHatasi ex =
new NesneYaratmaHatasi(clazz, e.getStackTrace());
throw ex;
}
}

/*
* (non-Javadoc)
*
* @see com.articles.generics.objectcaching.Pool#pull()
*/
public T cek() {
T object = havuz.remove(0);
return object;
}

/*
* (non-Javadoc)
*
* @see com.articles.generics.objectcaching.Pool#push(com.articles.generics.objectcaching.CachableObject)
*/
public **** koy(T object) {
havuz.add(object);
}

/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#bos()
*/
public boolean bos() {
return this.havuz.isEmpty();
}}


NesneHavuzu sınıfına dikkat edersek : Havuz arayüzündeki tip parametresi
<T extends Yedeklenebilir> burada da mevcut. Neden böyle? Bakalım:

NesneHavuzu sınıfında <T extends Object> tanımını kullanıp derlemek istediğimizde :

5960_image004.jpg


şeklinde bir uyarı ile karşılaşırdık. Bu uyarıda NesneHavuzu sınıfı tanımlamasındaki tip parametresi, Havuz arayüzünün beklediği tip parametresinin sınırları dışında oluduğu belirtilmektedir.

NesneHavuzu sınıfında <T extends X_Nesne> tanımını kullanıp derlemek istediğimizde herhangi sorun ile karşılaşmayız çünkü T tip parametresi Havuz arayüzünün beklediği sınırlar yani Yedeklenebilir arayüzünün alt hiyerarşisi içerisindedir.

Peki Havuz arayüzünün tanılamasını public interface Havuz <T> şeklinde değiştirdiğimiz de ne olur? Birşey olmaz çünkü böyle yaparak Havuz arayüzü üzerindeki kısıtlamayı kaldırıp bu arayüzü her tipten yapı için çalışır duruma getirmiş oluruz, standart Java paketi içerisindeki torba (Hash, List ...) yapılarında olduğu gibi.

Şimdi de şöyle bişey deneyelim. Havuz arayüzünü eski haline getirelim ama bu sefer NesneHavuzu sınıfı tanımını NesneHavuzu<T> implements Havuz<T> şeklinde değiştirelim. Derlemek istediğimiz de

5960_image004.jpg


<T extends Object> örneğimizde olduğu gibi yine aynı nedenden dolayı derleme zamanında uyarı alırız.

Peki alt hiyerarşi sınırlandırması için bir tanımlama mevcutken üst hiyerarşi sınırlandırması için bir tanımlama mevcut mu? <T super Yedeklenebilir> Yedeklenebilir arayüzünün üst hiyerarşisi için sınırlama yapılır.

Şimdiye kadar yazmış olduğumuz yapıların testini gerçekleştirelim.

public class HavuzTest extends TestCase {
private X_Nesne x_n1 = new X_Nesne();
private X_Nesne x_n2 = new X_Nesne();
private Y_Nesne y_n1 = new Y_Nesne();
private Y_Nesne y_n2 = new Y_Nesne();

Object obje_1 = new Object();

private NesneHavuzu<X_Nesne> x_havuz = new NesneHavuzu<X_Nesne>();
private NesneHavuzu<Y_Nesne> y_havuz = new NesneHavuzu<Y_Nesne>();
private NesneHavuzu<Yedeklenebilir> genel_havuz = new NesneHavuzu<Yedeklenebilir>();

public **** testCek() {
X_Nesne x_nesne_1 = x_havuz.cek();
// Y_Nesne x_nesne_2 = x_havuz.cek(); Derleme hatasi verir
Y_Nesne y_nesne_1 = y_havuz.cek();


// Cek yordami Yedeklenebilir tipinde değer dönerken
// biz X_Nesne tipinde bekliyoruz.
// X_Nesne x_nesne_3 = genel_havuz.cek();

X_Nesne x_nesne_3 = (X_Nesne) genel_havuz.cek();

}

public **** testKoy() {
x_havuz.koy(x_n1);
x_havuz.koy(x_n2);
// x_havuz.koy(y_n1); Derleme hatasi verir

y_havuz.koy(y_n1);
y_havuz.koy(y_n2);

genel_havuz.koy(x_n1);
genel_havuz.koy(y_n1);

// x_havuz.koy(obje_1); DERLEME HATASI
// y_havuz.koy(obje_1); DERLEME HATASI
// genel_havuz.koy(obje_1); DERLEME HATASI
}

}


HavuzYoneticisi Arayüzü



public interface HavuzYoneticisi {

<T extends Yedeklenebilir> **** nesneKoy(T nesne) throws NesneYaratmaHatasi;

<T extends Yedeklenebilir> T nesneCek(Class<T> clazz) throws NesneYaratmaHatasi;

<T extends Yedeklenebilir> **** havuzuKontrolEt(Class<T> clazz) throws NesneYaratmaHatasi;
}


Burada dikkat etmemiz gereken, arayüzü değil arayüz içerisindeki yordamları genelleştiriyor olmamız. <T extends Yedeklenebilir> tip parametresi korunarak yine hiyerarşi sınırlandırması yapmış oluyoruz. Eğer HavuzYoneticisi arayüzünü de <T extends Yedeklenebilir> tip parametresi ile genelleştirmiş olsaydık sadece tek tip bir yapı için çalışıyor hale gelirdi. Tıpkı Havuz arayüzü gibi :

NesneHavuzu<X_Nesne> x_havuz = new NesneHavuzu<X_Nesne>();


NesneHavuzuYoneticisi Sınıfı



public class NesneHavuzuYoneticisi implements HavuzYoneticisi {

private Map<Class<? extends Yedeklenebilir>,
Havuz<? extends Yedeklenebilir>>
havuzMap = new HashMap<
Class<? extends Yedeklenebilir>,
Havuz<? extends Yedeklenebilir>>();

@SuppressWarnings("unchecked")
public <T extends Yedeklenebilir> **** havuzuKontrolEt(Class<T> clazz)
throws NesneYaratmaHatasi {
Havuz<T> havuz = (Havuz<T>) havuzMap.get(clazz); // unchecked
if (havuz == null) {
havuz = new NesneHavuzu<T>();
havuzMap.put(clazz, havuz);
}

if(havuz.bos()){
havuz.doldur(clazz, 20);
}
}

@SuppressWarnings("unchecked")
public <T extends Yedeklenebilir> T nesneCek(Class<T> clazz)
throws NesneYaratmaHatasi {

havuzuKontrolEt(clazz);
Havuz<T> pool = (Havuz<T>) havuzMap.get(clazz);
T object = pool.cek();
return object;
}

@SuppressWarnings("unchecked")
public <T extends Yedeklenebilir> **** nesneKoy(T nesne)
throws NesneYaratmaHatasi {
havuzuKontrolEt(nesne.getClass());
Havuz<T> pool = (Havuz<T>) havuzMap.get(nesne.getClass());
pool.koy(nesne);
}

public static **** main(String[] args) {

NesneHavuzuYoneticisi opm = new NesneHavuzuYoneticisi();
try {
X_Nesne xnesne_1 = opm.nesneCek(X_Nesne.class);
X_Nesne xnesne_2 = opm.nesneCek(X_Nesne.class);
Y_Nesne ynesne_1 = opm.nesneCek(Y_Nesne.class);
Y_Nesne ynesne_2 = opm.nesneCek(Y_Nesne.class);
opm.nesneKoy(xnesne_1);
opm.nesneKoy(xnesne_2);
opm.nesneKoy(ynesne_1);
opm.nesneKoy(ynesne_2);
} catch (NesneYaratmaHatasi e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


NesneHavuzuYoneticisi sınıfında şu ana gördüğümüz genel tip tanımlarından farklı bir kaç ifade dikkatimizi çekmekte:

1. <? extends Yedeklenebilir> ifadesi
2. @SuppressWarnings("unchecked") ifadesi

Öncelikle havuzMap isimli HashMap nesnesinin tanımını inceleyelim. NesneHavuzuYöneticisi sınıfından beklentimiz �com.articles.generics.objectcaching. X_Nesne� sınıf ismini verdiğimizde bize bu sınıfın ilişkilendirildiği Havuz nesnesinden X_Nesne tipinde bir nesne çekmesi ve çekilen nesneyi ilgili havuza geri koymasıdır. Bunun için Class/Havuz, anahtar/değer (key/value) çitftine göre tanımlamış bir Map nesnesi oluşturmamız gerekli. Bu Map nesnesinin tanımına baktığımızda �?� karakteri dikkatimizi çekmektedir. Nedir bu karakterin sırrı?


WildCard �?�



Oluşturalan Map tipindeki nesnenin anahtar ve değer çiftinde sınırlama yapabilir miyiz? Bunun için wildcard denilen �?� karakterini kullanacağız. <? extends Yedeklenebilir> ifadesi Yedeklenebilir yapısına bir şekilde erişmiş (arayüzü gerçekleştirmiş yada sınıftan türemiş) herhangi bir yapı anlamına gelir. NesneHavuzuYoneticisi sınıfı içerisindeki Map nesnesinin tutacağı tipten emin olamayacağımız için WildCard kullanmaktayız.

Peki sistem Map içerisindeki anahtar/değer çiftini orjinal tipleri üzerinden mi iş görecek yoksa Yedeklenebilir yapısı üzerinden yukarı tip çevrimi (upcasting) yaparak mı iş görecek? Tabi ki sınır olarak verilen tip üzerinden çalışacaktır.

Gelin wildcard tanımlamasını basit bir örnek üzerinde inceleyelim :

class Tip_1 {
public **** benKimim(){
System.out.println("Ben Tip_1 im.");
}
}

class Tip_2 extends Tip_1{
public **** benKimim(){
System.out.println("Ben Tip_2 im.");
}

public **** benNeredeyim(){
System.out.println("Ben JVM deyim.");
}
}

1. class Torba <T>{
List<T> list = new ArrayList<T>();

2. public static **** yazdir(Torba t){
for(Object tip : t.list){
if(tip instanceof Tip_1){
((Tip_1) tip).benKimim();
} else if(tip instanceof Tip_2){
((Tip_2) tip).benKimim();
((Tip_2) tip).benNeredeyim();
}
}
}
}

public class Deneme_1 {


public static **** main(String[] args) {
Torba<Tip_1> torba_1 = new Torba<Tip_1>();
Torba<Tip_2> torba_2 = new Torba<Tip_2>();
Torba<Object> torba_3 = new Torba<Object>();
Torba.yazdir(torba_1);
Torba.yazdir(torba_2);
Torba.yazdir(torba_3);
}

}


1. satırda görüldüğü gibi Torba arayüzü herhangi bir sınırlama yapılmadan genelleştirilmiştir.
2. satırdaki yazdir static yordamı ise genelleştirmeden kurtarılmış düz Torba nesnelerini almaktadır. Bu şu anlama gelmekte : genelleştirmesi kaybolan nesnelerin içerisindeki tanımlı yordam ve değişkenler, eskisi gibi Object tipine yada <? extends X> ifadesindeki X ile belirtilen sınır tipine dönüştürülerek kullanılacaktır. For döngüsü içerisinde instanceOf kullanarak tip belirlemesi ve çevrimi (upcasting/downcasting) yapabiliriz.

Peki 2. satırdaki yordam tanımını aşağıdaki gibi değiştirirsek

public static **** yazdir(Torba<?> t)

değişen birşey olmayacaktır. Yukarıda da belirtildiği gibi �?� karakteri belirsizlik belirtmektedir ve bu belirsizliğin en üst sınırı Object tipidir. Aşağıdaki kod hala geçerlidir.

Torba<Object> torba_3 = new Torba<Object>();
Torba.yazdir(torba_3);


Wildcard �?� karakterini sınırlamak için

public static **** yazdir(Torba<? extends Tip_1> t)

kullanılır. Artık aşağıdaki kod derleme zamanında hata verecektir.

Torba<Object> torba_3 = new Torba<Object>();
Torba.yazdir(torba_3);





@SuppressWarnings("unchecked")



SuperWarnings, Java 1.5 içerisinde tanımlı olan annotation�dır. Bu tanımlama, eski kod / jenerik kod dönüşümünde yada jenerik yapıların kendi içerisindeki belirsiz dönüşümlerinde JVM�e derleme zamanında dönüşüm kontrolünün yapılmamasını belirtir.

NesneHavuzuYoneticisi sınıfı içerisideki nesneCek() yordamında bu tanımlama kullanılmıştır. Çünkü

@SuppressWarnings("unchecked")
public <T extends Yedeklenebilir> T nesneCek(Class<T> clazz)
throws NesneYaratmaHatasi {

havuzuKontrolEt(clazz);
Havuz<T> pool = (Havuz<T>) havuzMap.get(clazz);
T object = pool.cek();
return object;
}

yordamını aşağıdaki gibi çağırdağımızda

X_Nesne t_nesne = nesneHavuzYoneticisi.nesneCek(X_Nesne.class);

havuzMap değişkeni içerisinden Yedeklenebilir tipine genelleştirilmiş (bkz. NesneHavuzuYoneticisi sınıfı havuzMap değişken tanımı) Havuz nesnesi çekilir ve sonrasında (Havuz<T>) yani (Havuz<X_Nesne>) tipine dönüşüm yapılır. Bu dönüşüm sırasında sistem dönüştürülecek olan Havuz nesnesinin hangi tip için genelleştirildiğini bilemediğinden � poolMap değişken tanımlamasındaki Havuz<? extends Yedeklenebilir> ifadesinden kaynaklanmaktadır - derleme zamanında tip dönüşüm kontrolünü kaldırmalıyız. Bunun için

SuppressWarnings("unchecked")

ifadesini kullanılır.


Jenerik Yordamlar



Sınıf veya arayüzler gibi yordamlarda genelleştirilebilir. NesneHavuzuYoneticisi sınıfı genelleştirilmemesine rağmen içerisindeki yordamlar genelletirilmiştir.

public <T extends Yedeklenebilir> T nesneCek(Class<T> clazz)

yordamını ele alalım. T tip parametresi, nesneCek() yordaminin dönüş tipi olarak kullanılmış hem de bu yordama gelen Class parametresini sınırlandırmıştır. nesneCek() yordamının aşağıdaki çağrılış şekline baktığımızda dikkatimi bir şey çekmeli:

X_Nesne t_nesne = nesneHavuzYoneticis.nesneCek(X_Nesne.class);

herhangi bir tip parametresi belirtilmemiş. Sistem gönderilen parametrelerin tipine göre genel tip parametrelerini bizim yerimize ayarlamaktadır.

Jenerik yordamları bir örnek ile daha detaylı inceleyelim:

public class JenerikYordamlar {

public static <T> **** copy(List<T> hedefListe, List<? extends T> kaynakListe){
Collections.copy(hedefListe, kaynakListe);
}

public static <T, S extends T> **** copyV2(List<T> hedefListe, List<S> kaynakListe){
Collections.copy(hedefListe, kaynakListe);
}

public static **** main(String args[]){
Vector<Tip_1> anaListe= new Vector<Tip_1>(10);
anaListe.setSize(10);
Vector karisikListe = new Vector(10);
karisikListe.add(new Object());
JenerikYordamlar.copy(anaListe, karisikListe);
for(Tip_1 tip1 : anaListe){
tip1.benKimim();
}
}
}


Yukarıdaki JenerikYordamlar sınıfında jenerik tip parametreleri farklı olan ama aynı işi yapan copy() ve copyV2() yordamlarını tanımlayalım. Bu yordamların görevi kaynakListe listesindeki nesneleri hedefListe listesinin içerisine kopyalamak olsun. Kopyalama işlemi için Collections sınıfı içerisindeki static copy() yordamını kullanalım.

Yukarıdaki kodu derlemeye çalıştığımızda :

5960_image007.jpg


şeklinde uyarı mesajı alırız.

Birinci mesajda JenerikYordamlar.copy() yordamında ikinci parametre tipi olarak Vector<? extends T> yani Vector<? extends Tip_2> beklerken eski tip Vector nesnesi yollanmaya çalışılmış. Burada derleme zamanında tip kontrolünü kaldırmamız gerekli.

İkinci uyarı mesajında ise birinci uyarıdan kaynaklanan ve yordam tanımlamasındaki tip parametreleri ile yordam çağrımında gönderilen nesnelerin tip parametreleri arasındaki uyumsuzluktan bahsedilmektedir.

Main() statik yordamına @SuppressWarnings("unchecked") ekleyerek uyarısız bir şekilde derleme işlemini gerçekleştirebiliriz ama bu çalışma zamanında istenmeyen sorunlara neden olabilir. Çünkü eski şekilde yaratılan karisikListe içerisine Object nesnesi attığımız zaman bu nesne hedef listeye anaListe nin tip parametresi olan Tip_1�e çevrilerek (downcasting) kopyalanır. anaListe içerisindeki nesnelerin benKimim() yordamını çağırmaya kalktığımızda

5960_image009.jpg


hata mesajını alırız.

Aşağıdaki gibi kodu değiştirdiğimiz de:

public static **** main(String args[]){
Vector<Tip_2> anaListe= new Vector<Tip_2>(10);
anaListe.setSize(10);
Vector<Tip_1> karisikListe = new Vector<Tip_1>(10);
karisikListe.add(new Tip_1());
JenerikYordamlar.copy(anaListe, karisikListe);
JenerikYordamlar.copyV2(anaListe, karisikListe);
}

derleme zamanında aşağıdaki hataları alırız :

5960_image011.jpg


Bu hata mesajlarından yola çıkarak copy() ve copyV2() yordamları sınırları ve işlevleri aynı iki yordam diyebiliriz.

Standart Java paketi içerisindeki Collections sınıfının copy() yordamına bakalım. Bu yordamın tanımı

copy(List <? super T> arg0, List<? extends T> arg1)

şeklindedir. Burada da T ve T tipi hiyerarşisi altındaki nesneleri barındıran liste sadece T ve T tipi hiyerarşisi üstündeki tipler için tanımlanmış listeye kopyalanması kuralı gerçekleştirilmiştir.

Sonuç



Genel tipler ilk başlarda kullanması ve okuması zor görünse de tip dönüşüm hatalarının derleme zamanına taşınması beklenmedik hataların oluşmasını azaltmaktadır. Bu da uygulama içerisinde genel tiplerin kullanımının ve tip sınırlamalarının ne kadar iyi yapıldığına bağlıdır.

Kaynaklar



1. http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
2. Diagnosing Java code: Java generics without the pain : A guide to generics in the Java Tiger version and the JSR-14 prototype compiler ; Eric Allen ([email protected]), Ph.D. candidate, Java programming languages team, Rice University
3. Generics Considered Harmful by Ken Arnold
4. Generics Aren't by Bruce Eckel
5. Generic Types; by David Flanagan

 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.