7 Mayıs 2016 Cumartesi

-Java Reflection Kullanımı -

Merhabalar,
Android Framework API geliştirirken,cihazın SIM kartları ile ilgili birtakım bilgileri kullanmam gerekiyordu.
Bu bilgilerin bulunduğu Java sınıfları(class) farklı dizinde ve paket içersinde bulunuyordu. 
İlgili class'lara Reflection(yansıtma) ile erişmeyi ve gerekli fonksiyon ve parametreleri kullandım.

Reflection; Java sınıflarına(class) erişim ve içeriğini kullanabilmek için geliştirilmiş bir kütüphanedir.
Reflection kütüphanesi 'java.lang.reflect' paketi altında bulunur. Bu paket altında bulunan Interface,Class ve Exception kalıplarıyla
Class'lar üzerinde esnek işlemler uygulamak mümkündür. Ancak bu makalede tüm 'java.lang.reflect' paket içeriğini değil,sadece 'Method' Class içersinde birkaç özellik kullanacağız.
İlk olarak 'Reflection' kavramını anlayabilmemiz için aşağıdaki basit örnek uygulama geliştirilmiştir.
Uygulama için 'MyClass' isminde bir Class oluşturuldu ve semboilk fonksiyonlar eklendi.
Örnek:

-MyClass.java:
package com.java.reflection;
public class MyClass {

private String name;
private int age;
private int ID;
public MyClass(){
///..
}

public void setName(String _name){
        name = _name;
}
public String getName(){
return name;
}

public void setAge(int _age){
age = _age;
}
public int getAge(){
return age;
}

public String toString(){
return name +" " + age; 
}
}

-Main.java:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) {
/*
* MyClass.java Classı içersinde bulunan fonksiyonları-methodları listeleyeceğiz.
* Fonksiyonları elde edebilmek için 'reflect' paketi altında bulunan 'Method' Class'ı kullanılıyor.
*/
Method[] methods = MyClass.class.getMethods();//fonksiyon dizisi.
for(Method method: methods){//fonksiyon elde etme.
String name = method.getName();//fonksiyon ismine erişim.
System.out.println(name);
}

}
}
Çıktı:
toString
getName
setName
setAge
getAge
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll

NOT: Java'da her Class aslında 'Object' class'ı taban alır. Yani gizli bir 'extends' işlemi uygulanır.
Bu durumda oluşturmuş olduğumuz 'MyClass' aslında 'Myclass extends Object' şeklinde konum alır.
Dolayısıyla yukarıdaki çıktıda Object class içeriğine ait fonksiyonlar da listelenmiştir.
Ancak aşağıda verilen örnekte sadece 'MyClass' içeriğine ait fonksiyonlar listelenecektir(kullanım farkını inceleyiniz).

Reflection işleminde belirtilen Class içeriğine ait fonksiyonları aşağıdaki gibi de elde edebiliriz.
Örnek:
public class Main {
public static void main(String[] args) {
try {
//erişilecek Class ismi paket ismi dahil açık şekilde belirtiliyor.
Class cls = Class.forName("com.java.reflection.MyClass");
//getDeclaredMethod fonksiyonu ile tüm fonksiyonlar Method[] dizi türünden döndürülüyor.
Method[] methods = cls.getDeclaredMethods();
for(Method method:methods){
System.out.println(method.getName());
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
Çıktı:
toString
getName
setName
setAge
getAge


Reflection kavramını biraz daha ileri götürelim ve MyClass içersinde bulunan fonksiyonlara parametre gönderip işletelim.
Aşağıda verilen örneği ve çıktıyı inceleyiniz.
Main.java:
public class Main {
public static void main(String[] args) {
try {
//erişilecek Class ismi paket ismi dahil açık şekilde belirtiliyor.
Class cls = Class.forName("com.java.reflection.MyClass");
//MyClass için instance oluştur.
Object obj =cls.newInstance();
/*setName fonksiyonu elde etmek için getMethod 1.parametre fonksiyon ismi,
* 2.parametre ise setName fonksiyonuna ait parametre türü belirleniyor.
* setName fonksiyonumuz 'String' türünde bir parametre aldığı için 'String.class'
* referansı belirleniyor.
* Bu durumda int parametre alan setAge fonkisyonunu için 'Integer.TYPE' belirlenmelidir.

*/
Method method1 = cls.getMethod("setName", String.class);
//fonksiyonumuzun ismi:
       System.out.println(method1.getName());
       //fonksiyonumuzun geri döndürdüğü değer tipi:
       System.out.println( method1.getReturnType());
       //invoke ile setName fonkisyonuna parametre gönderiyoruz:
       method1.invoke(obj, "KERİM FIRAT");
       
       /*setName fonksiyonunu çağırmak için nesneler oluşturuluyor.
        * cls.getMethod 2. parametrenin 'null' olduğuna dikkat edin.
        * Şayet bir fonksiyon parametre almıyorsa buraya null değer geçilir.
        * Aynı durum invoke çağrıldığında da uygulanmalıdır.
        */
       Method method2 = cls.getMethod("getName", null);
       //fonskiyon değeri elde etmek için invoke çağrılıyor:
       Object return_value1 = method2.invoke(obj, null);
       System.out.println("Adı-Soyadı:"+return_value1.toString());
       
       Method method3 = cls.getMethod("setAge", Integer.TYPE);
       method3.invoke(obj, 34);
       Method method4 = cls.getMethod("getAge", null);
       Object return_value2 = method4.invoke(obj, null);
       System.out.println("Yaş:"+return_value2);
           
}catch (Exception e) {
e.printStackTrace();
}
}
}
Çıktı:
setName
void
Adı-Soyadı:KERİM FIRAT
Yaş:34

Not:
Reflect paketi inceleme:https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/package-summary.html
Method Class inceleme: https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html
İyi çalışmalar.

Hiç yorum yok:

Yorum Gönder