3 Aralık 2007 Pazartesi

Java Reflection Nedir, Nasıl Kullanılır??

Java Reflection bir uygulama geliştirme arayüzü olup, o anki Java Sanal Makinesindeki sınıfları, arayüzleri ve nesneleri yansıtan, temsil eden kütüphanedir. Özellikle geliştirme araçları yazarken yansıtma kütüphanesine ihtiyaç duyarız. Yansıtma kütüphanesini kullanarak;

Bir nesnenin sınıfını belirleriz

Sınıfın sahaları, metodları, yapıcıları, üst sınıfları ve değişkenleri hakkında bilgiler alabiliriz

Bir arayüze ait olan sabit ve metod tanımlamalarını tespit ederiz

Çalışma zamanına kadar ismi bilinmeyen bir sınıf örneği yaratabiliriz (Bir bakıma çalışma zamanında yeni sınıflar yaratabilirsiniz)

Çalışma zamanına kadar ismi bilinmese de sahaların değerini ayarlar ve alabiliriz.

Aynen çalışma zamanına kadar bilinmeyen metodları çalıştırabiliriz.

Çalışma zamanına kadar bileşenleri ve boyutu bilinmeyen diziler yaratabilir, daha sonra bu dizinin bileşenlerini değiştirebiliriz.

Çok önemli bir hatırlatma, standart java yapılarıyla yapabileceğiniz işleri Java yansıtma kütüphanesiyle yapmamalıyız. Umulmadık zorluklar ve sorunlarla karşılaşabiliriz.

Şimdi aşama aşama yansıtma kütüphanesini inceleyelim. Temel olarak yapmak istediğimiz ilk işlem bir nesnenin hangi sınıfa ait olduğunu bulmaktır. Sınıfı bulduktan sonra bu sınıf yardımıyla yansıtma kütüphanesinin tüm nimetlerinden faydalanabiliriz. Bunu yapmak için nesne.getClass() (Class döndürmektedir) çağrımında bulunuruz. Bu aldığımız Class tipinde nesneyi kullanarak nesnemizin metodlarını listeleyebilir, sahalarını listeleyebilir, istediğimiz sahanın get ve set metodlarını bulup çalıştırabiliriz.


Aşağıda çok basit bir, nesnenin tüm metodlarını ekrana yazdıran kodu görebilirsiniz:

import java.lang.reflect.*; //Bize gerekecek tum siniflar bu pakette
import java.util.ArrayList;

public class MetodYazdir {
public static void main(String[] args) {
try {
//Once ArrayList sinifinin Class nesnesini alalim
//getClass() metodu da kullanilabilir
Class c = ArrayList.class;
//Daha sonra bu sinif icerisindeki tum metodlari cekelim
Method[] m = c.getDeclaredMethods();

//Ve bu metod dizisini dolasarak bilgilerini ekrana yazalim
for (int i = 0; i <>
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}

Bu kodu çalıştırdığınız zaman


public void java.util.ArrayList.add(int,java.lang.Object)
public boolean java.util.ArrayList.add(java.lang.Object)
public java.lang.Object java.util.ArrayList.clone()
…………………………………
Şeklinde uzayıp giden ve ArrayList sınıfının metodları erişim ve parametre bilgilerini gösteren çıktıyı göreceksiniz.

Bir yansıtma işlemi yapabilmek için temel olarak ilk yapılması gereken Class nesnesine ulaşmaktır. Bunun için farklı yöntemler vardır.

Class c = Class.forName("java.lang.String");
Class c = int.class;
Class c = Integer.TYPE;
Class c = Ogrenci.getClass();

Bu Class nesnesini aldıktan sonra bu nesne içerisindeki metodlar kullanılarak her türlü bilgi (sınıfla ilgili olan) rahatça alınabilir. Aşağıdaki bağları inceleyerek bu konuda hakkında daha ayrıntılı bilgilere ulaşabilirsiniz. Ayrıca örnek kodların (açıklamalı) içerisindeki ClassParser sınıfını her türlü projenizde ihtiyaçlarınız doğrultusunda kullanabiliriz.

Java.lang.reflect PAKETİ:

Class lar ve object ler hakkında yansıtıcı bilgi elde etmek için arayüzler ve sınıflar sağlar.

java.lang.reflect paketi tanımı

reflection(yansıma)yüklü olan class ların yapıcı fonksiyonları,alanları ,metotları hakkında bilgiye programlı erişim sağlar ve reflected(yansımış) alanları,metotları ve yapıcı fonksiyonları, nesnelerin temelindeki gizli kısıtlamalarıyla kopyaları üzerinde işlem yapar.

Bu paketteki sınıflar ,java.lang.Class beraberinde debuggers,interpreters,object inspectors,class browsers ve object serialization ve verilen bir sınıf tarafından tanımlanmış üyeler veya hedef nesnenin public üyelerine erişime ihtiyacı olan javabeans gibi servis uygulamalrını birleştirir.

Bir sınıfın metodları hakkında bilgilenmek;

import java.lang.reflect.*;

public class MetodBilgi {

//Bu ornek metodu ekrana basilmasini bekliyoruz

private int f1(Object p, int x)

throws NullPointerException {

if (p == null) {

throw new NullPointerException();

}

return x;

}

public static void main(String[] args) {

try {

//MetodBilgi sinifinin Class nesnesini alalim

Class cls = Class.forName("MetodBilgi");

//Metod dizisini cekelim

Method[] methlist = cls.getDeclaredMethods()

//Bu metod dizisini dolasalim

for (int i = 0; i <>

//Dizideki her metod icin ekrana

Method m = methlist[i];

//ismini

System.out.println("isim :"

+ m.getName());

//tanimlandigi sinif bilgisini

System.out.println("tanimlandigi sinif :"

+m.getDeclaringClass());

//Parametre bilgilerini

Class[] pvec = m.getParameterTypes();

for (int j = 0; j <>

System.out.println("parametre #" + j

+ " " + pvec[j]);

//Firlattigi istisna bilgilerini

Class[] evec = m.getExceptionTypes();

for (int j = 0; j <>

System.out.println("exception #"

+ j + " " + evec[j]);

//Metodun geri donus degerini

System.out.println("donus tipi = "

+ m.getReturnType());

//yazalim

System.out.println("-----");

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

Yapıcılar hakkında bilgilenmek;

import java.lang.reflect.*;

public class YapiciBilgi {

public YapiciBilgi() {

}

protected YapiciBilgi(int i, double d) {

}

public static void main(String[] args) {

try {

Class cls = Class.forName("YapiciBilgi");

//Bu sekilde bu sinif icerisinde tanimlanmis olan

//yapicilarin dizisini aliyoruz

Constructor[] ctorlist = cls.getDeclaredConstructors();

for (int i = 0; i <>

Constructor ct = ctorlist[i];

System.out.println("isim :"

+ ct.getName());

System.out.println("tanimlandigi sinif :"

+ct.getDeclaringClass());

Class[] pvec = ct.getParameterTypes();

for (int j = 0; j <>

System.out.println("parametre #"

+ j + " " + pvec[j]);

Class[] evec = ct.getExceptionTypes();

for (int j = 0; j <>

System.out.println("exception #"

+ j + " " + evec[j]);

System.out.println("-----");

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

Sahalar hakkında bilgilenmek;

import java.lang.reflect.*;

public class SahaBilgi {

public static final int i = 37;

private double d;

String s = "deneme";

public static void main(String[] args) {

try {

Class cls = Class.forName("SahaBilgi");

//Bu sekilde bu sinifin icerisinde tanimlanmis

//sahalarin dizisine erisiriz

Field[] fieldlist = cls.getDeclaredFields();

//Bu diziyi dolasiriz

for (int i = 0; i <>

//dizideki her eleman icin

Field fld = fieldlist[i];

//sahanin ismini

System.out.println("isim :"

+ fld.getName());

//tanimlandigi sinifi

System.out.println("tanimlandigi sinif :" +

fld.getDeclaringClass());

//tipini

System.out.println("tipi :"

+ fld.getType());

int mod = fld.getModifiers();

//ve resmi bir bicimde private,public,static,final v.b.

//erisim bilgilerini

System.out.println("modifier :"

+ Modifier.toString(mod));

//ekrana yazariz

System.out.println("-----");

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

İsmini kullanarak metodları çalıştırma;

import java.lang.reflect.*;

public class MetodCalistirma {

public int add(int a, int b) {

return a + b;

}

public static void main(String[] args) {

try {

//Sinifi alalim

Class cls = Class.forName("MetodCalistirma");

//Gonderecegimiz parametre tiplerini ayarliyoruz

Class[] partypes = new Class[2];

//Iki parametresi de Integer tipinde olan metod

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

//adi 'add' olan ve partypes parametre tiplerine sahip

//metodu aliyoruz

Method meth = cls.getMethod("add", partypes);

//Metodu uzerinde calistiracagimiz nesne ornegini

//yaratalim

MetodCalistirma methobj = new MetodCalistirma();

//Gonderecegimiz parametre listesini yaratalim

Object[] arglist = new Object[2];

//Parametreler Integer tipinde

//Birincisi 37 degerinde

arglist[0] = new Integer(37);

//Ikincisi 47 degerince

arglist[1] = new Integer(47);

//Daha sonra onceden bulmus oldugumuz metodu

//yarattigimiz methobj uzerinde arglist argumanlari

//ile calistiralim

Object retobj = meth.invoke(methobj, arglist);

//Donen degeri uygun tipe dondurur

Integer retval = (Integer) retobj;

//Ekrana yazalim Sonuc olacak 37+47=84 ekrana

//yazilacaktir

System.out.println(retval.intValue());

} catch (Throwable e) {

System.err.println(e);

}

}

}

Yeni nesneler yaratmak

import java.lang.reflect.*;

public class NesneYarat {

public NesneYarat() {

}

public NesneYarat(int a, int b) {

System.out.println("a = " + a + " b = " + b);

}

public static void main(String[] args) {

try {

Class cls = Class.forName("NesneYarat");

//Bulacagimiz yapici metodun parametre tiplerini

//ayarlayalim

Class[] partypes = new Class[2];

//Bulacagimiz yapici Integer tipinde iki

//parametre aliyor

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

//Yarattigimiz parametre tiplerini alan

//yapiciyi sinifta bulalim

Constructor ct = cls.getConstructor(partypes);

//Bu yapici calistirirken gonderecegimiz

//argumanlari yaratalim

Object[] arglist = new Object[2];

arglist[0] = new Integer(37);

arglist[1] = new Integer(47);

//Ve bu argumanlari kullanarak bu yapiciyi

//calistiralim

//Yapici metodun calismasi sonunda elimizde

//NesneYarat tipinde bir ornek oldu

Object retobj = ct.newInstance(arglist);

//Ekrana bu olusan nesnenin basit sinif ismini

//(paket bilgisi olmadan) yazalim

System.out.println(retobj.getClass().getSimpleName());

} catch (Throwable e) {

System.err.println(e);

}

}

}

Saha değerini değiştirmek;

import java.lang.reflect.*;

public class DegerDegistirme {

public double d;

public static void main(String[] args) {

try {

Class cls = Class.forName("DegerDegistirme");

//Sinifin 'd' isimli sahasini alalim

Field fld = cls.getField("d");

//Deger degistirme uygulayacagimiz nesne ornegini

//yaratalim

DegerDegistirme f2obj = new DegerDegistirme();

//Sahanin degisimden onceki degerini ekrana basalim

System.out.println("d = " + f2obj.d);

//Degerini 12.34 ile degistirelim

//Eger tipini biliyorsak o tipe uygun set ve get

//metodlari kullanilarak sahalarin degerleri ayarlanir

//ve alinir

fld.setDouble(f2obj, 12.34);

//Ekrani degisimden sonraki degeri basalim

System.out.println("d = " + f2obj.d);

} catch (Throwable e) {

System.err.println(e);

}

}

}

Dizi kullanimi;

import java.lang.reflect.*;

public class Dizi {

public static void main(String[] args) {

try {

//String tipinde Class nesnesini olusturalim

Class cls = Class.forName("java.lang.String");

//Bu Class nesnesi tipinde 10 elemanli bir dizi olusturalim

Object arr = Array.newInstance(cls, 10);

//5. elemani "Bu bir deneme" seklinde ayarlayalim

Array.set(arr, 5, "Bu bir deneme");

//5. elemani cekelim

String s = (String) Array.get(arr, 5);

//Ekrana basalim

System.out.println(s);

} catch (Throwable e) {

System.err.println(e);

}

}

}

Daha karmaşık dizi örneği

import java.lang.reflect.*;

public class KarmasikDizi {

public static void main(String[] args) {

int[] dims = new int[] { 5, 10, 15 };

//Yukarida tanimladigimiz uzunluklarda 3 boyutlu dizi

//ornegi olusturalim

//Boyutlar sirasiyla 5,10 ve 15 uzunlugunda olacaktir

Object arr = Array.newInstance(Integer.TYPE, dims);

//Dizinin ucuncu elemanini alalim

Object arrobj = Array.get(arr, 3);

//Bu elemanin Class nesnesini alip

Class cls = arrobj.getClass();

//Ekrana tipini basalim (int[][])

System.out.println(cls.getSimpleName());

//Daha sonra ucuncu elemanin besinci elemanini

//alalim

arrobj = Array.get(arrobj, 5);

//Ve bu elemanin 10. elemanini 37 olarak

//ayarlayalim

Array.setInt(arrobj, 10, 37);

//Olusturdugumuz nesneyi tipine donusturup

int[][][] arrcast = (int[][][]) arr;

//Degistirdigimiz elemani ekrana yazalim

System.out.println(arrcast[3][5][10]);

}

}

Hiç yorum yok: