Bu Sayfayı Paylaş:

Kavram

Generics

Tanım: Programlama dillerinde bir sınıfın veya method'un genel olarak tanımlanması ancak özel ve farklı sınıflara göre çalışbilmesini sağlamak (bir çeşit şablon sınıf yaratmak) amacıyla kullanılan özellik. Bir sınıfın object sınıfına göre çalışması yerine generics kullanıldığında tip güvenliği de sağlanmaktadır

Örnek

Basit Bir Generics Örneği

Aşağıda herhangi bir T tipinde sınıf için çalışan ve kendisine nesne eklenmesini ve alınmasını sağlayan örnek

public class GenericTest<T> {
    private Object[] objects=new Object[10];    
    public void add(int i,T o){
        objects[i]=o;
    }
    public T get(int i){
        return (T)objects[i];
    }
}

Sınıf GenericTest şeklinde tanımlanarak herhangi bir sınıf için çalışması sağlanmıştır. Kullanırken aşağıdaki gibi kullanılabilir :

GenericTest<String> gtS=new GenericTest<String>();
GenericTest<Integer> gtInt=new GenericTest<Integer>();
GenericTest<Date> gtDate=new GenericTest<Date>();
gtS.add(1,"Test 1");
gtInt.add(1,1);
gtDate.add(1,new Date());

Görüldüğü gibi bir nesne new GenericTest<string>() şeklinde yaratılırsa ona ancak String tipinde veri eklenebilir

 


Örnek

Kalıtım Kullanılan Basit Bir Generics Örneği

Aşağıda belirli bir sınıftan türetilmiş sınıflar için çalışan generics sınıf örneği görülmektedir :
public class GenericTest<T extends GenericBaseTest> {
	...
}
Yukarıdaki GenericTest sınıfı sadece GenericBaseTest sınıfından türetmiş sınıflar için çalışacaktır. GenericBaseTestExt sınıfı GenericBaseTest sınıfından türemişse aşağıdaki gibi bir kod yazılabilir :
GenericTest<GenericBaseTestExt> gt=new GenericTest<GenericBaseTestExt>();

Örnek

Kalıtım Wildcard ve Super İfadesi Kullanılan Basit Bir Generics Örneği

Aşağıda belirli bir sınıftan türetilmiş sınıflar için çalışan generics sınıf örneği görülmektedir :
public class GenericTest<T extends GenericBaseTest> {
	...
}
Yukarıdaki GenericTest sınıfı sadece GenericBaseTest sınıfından türetmiş sınıflar için çalışacaktır. GenericBaseTestExt sınıfı GenericBaseTest sınıfından türemişse aşağıdaki gibi bir kod yazılabilir :
GenericTest<GenericBaseTestExt> gt=new GenericTest<GenericBaseTestExt>();
GenericTest<? extends GenericBaseTest> gtGeneral=gt;
Yukarıdaki örnekde gtGeneral nesnesi GenericBaseTest sınıfından türüyen herhangi bir sınıfla çalışabileceği anlamına gelmektedir.
GenericBaseTestExt'in genişlettiği GenericBaseTestExt2 sınıfı için aşağıdaki gibi kullanılabilir :
GenericTest<GenericBaseTestExt> gt=new GenericTest<GenericBaseTestExt>();
GenericBox<? super GenericBaseTestExt2> gtSuper=gt;

? super GenericBaseTestExt2 ifadesi GenericBaseTestExt2'in genişlettiği sınıf anlamına gelmektedir

İpucu

Generics Bir Parametrenin Sınıfının Alınması

Generic bir sınıf yaptığınızda , generic verilen parametrenin sınıfına ihtiyacınız olabilir. Normal durumda metot içinde verilen parametrenin sınıfını bulamazsınız. Örneğin JPA için genel bir data access sınıfı aşağıdaki gibi olsun :


import javax.persistence.EntityManager;
import javax.persistence.Persistence;
 
public class GenericDao<T,PK> {
             
	private EntityManager entityManager;
	public GenericDao() {
			   
		entityManager = Persistence.createEntityManagerFactory("TestJPA").createEntityManager();
			   
	}
	public Test find(Long id) {
		return entityManager.find(entityClass, id); // hata
	}
	public void create(Test t) {
		entityManager.persist(t);
	}
	public void update(Test t) {
		entityManager.merge(t);
	}
	public void delete(Test t) {
		entityManager.remove(t);
	}
 
}
Yukarıdaki kod derlenemez. entityManager.find(entityClass, id) satırında T'nin sınıfı gerekmektedir. Generic bir değişkenin sınıfını o anda alamazsınız. T'nin sınıfını almak için T sınıfı için kurucuda bir Class değişkeni yaratılabilir ve aşağıdaki gibi yaratılabilir :
import java.lang.reflect.ParameterizedType;
 
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
 
public class GenericDao<T, PK> {
 
	private EntityManager entityManager;
	protected Class<T> entityClass;
	public GenericDao() {
		entityManager = Persistence.createEntityManagerFactory("TestJPA").createEntityManager();
		ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
		entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
	}
	public T find(Long id) {
		return entityManager.find(entityClass, id); // hata
	}
	public void create(T t) {
		entityManager.persist(t);
	}
	public void update(T t) {
		entityManager.merge(t);
	}
	public void delete(T t) {
		entityManager.remove(t);
	}
 
}
Görüldüğü gibi kurucuda
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
 
entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];


ile T argümanın sınıfı tespit edilmiştir. Bu şekilde find metodunda kullanılabilir.



Bu Sayfayı Paylaş:

İletişim Bilgileri

Takip Et

Her Hakkı Saklıdır. Bu sitede yayınlanan tüm bilgi ve fikirlerin kullanımından fibiler.com sorumlu değildir. Bu sitede üretilmiş , derlenmiş içerikleri, fibiler.com'u kaynak göstermek koşuluyla kendi sitenizde kullanılabilirsiniz. Ancak telif hakkı olan içeriklerin hakları sahiplerine aittir