27 Ağustos 2014 Çarşamba

Java'da Reflection Kütüphanesi



 Genelde Java'da çalışma zamanında test yapmak için kullanılan Reflection(yansıma) kütüphanesini kullanarak yapabileceğimiz bazı ilginç şeyler var. 
İşte Reflection kütüphanesini kullanarak yapabileceğimiz birkaç şey;

1-  Normalde bir sınıfta tanımlanan private alanlara erişemediğimizi biliyoruz fakat bunu reflectionlar ile rahatça yapabiliriz. Mesela PrivateClass adında bir sınıfımız olsun ve içinde iki tane private değişken bulunsun.
package com.cengfurkan;

public class PrivateClass {

    private String ad = "Furkan";
    private int yas = 19;
}
bu sınıftaki private değişkenlere oluşturduğumuz Yansıma sınıfından ulaşmaya çalışalım

package com.cengfurkan;

import java.lang.reflect.Field;

public class Yansıma {
 public static void main(String[] args) {
  try {
   Class sınıf = Class.forName("com.cengfurkan.PrivateClass");
   Object object = sınıf.newInstance();
   Field[] fields = sınıf.getDeclaredFields();
   for (int i = 0; i < fields.length; i++) {
    fields[i].setAccessible(true);
    System.out.println("Verinin adı: " + fields[i].getName() + "\t"
      + "Verinin tipi: " + fields[i].getType().getName()+ "\t" 
      + "Verinin değeri: " + fields[i].get(object));
   }
  } catch (Exception e) {
   System.out.println("Hata: " + e.getMessage());
  }
 }
}
Ve ta da, PrivateClass sınıfındaki private değişkenlerin tipine ve içeriğine eriştik.

2- Normalde private yapıcı metodu olan bir sınıftan örnek üretemeyiz(Singleton desen hariç) Şimdi PrivateClass sınıfımızın içeriğini  değiştirelim ve tekrar Yansıma sınıfından bunu mümkün hale getirelim.



package com.cengfurkan;

public class PrivateClass {

 private String ad = "Furkan";
 private int yas = 19;

 private PrivateClass() {
  System.out.println("Merhaba!");

 }
} 
 package com.cengfurkan;

import java.lang.reflect.Constructor;

public class Yansıma {
 public static void main(String[] args) {
  try {
   Class sınıf = Class.forName("com.cengfurkan.PrivateClass");
   Constructor[] yMetotlar = sınıf.getDeclaredConstructors();
   System.out.println("Yapıcı Metot Adı"
     + yMetotlar[0].getName());
   yMetotlar[0].setAccessible(true);
   System.out.println("Sınıfın örneği: "
     + yMetotlar[0].newInstance());
  } catch (Exception e) {
   System.out.println("Hata: " + e.getMessage());
  }
 }
}

3- Şimdi de bir statik değişkeni değiştirmeye bakalım. İlginç geliyor değil mi?


package com.cengfurkan;

public class PrivateClass {

 private static String sehir = "Zonguldak";

 public static String sehirAl() {
  return sehir;
 }
}
Şehir adında bir static string değişkenimiz  ve onu return eden bir metodumuz var.


 package com.cengfurkan;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Yansıma {
 public static void main(String[] args) {
  try {
   Class sınıf = Class.forName("com.cengfurkan.PrivateClass");
   Field[] fields = sınıf.getDeclaredFields();
   fields[0].setAccessible( true );
   System.out.println(PrivateClass.sehirAl());
   fields[0].set( null ,"Eskişehir" );
   System.out.println(PrivateClass.sehirAl());
  } catch (Exception e) {
   System.out.println("Hata: " + e.getMessage());
  }
 }
}
Artık statick değişken olan sehir değişkeni Eskişehir olarak değişti.

4- Benzer bir yolla bu sefer private metotlara erişmeyi deneyelim

 package com.cengfurkan;

public class PrivateClass {

 private static String sehir = "Zonguldak";
 private int plakaKodu = 67;

 private String sehirAl() {
  return sehir;
 }

 private int kodAl() {
  return plakaKodu;
 }
}
görüldüğü gibi iki tane private değişken ve bunları return eden private metodlarımız var. Şimdi Yansıma sınıfından bu metodlar hakkında hangi bilgileri bulabiliyoruz bakalım
 package com.cengfurkan;

import java.lang.reflect.Method;

public class Yansıma {
 public static void main(String[] args) {
  try {
   Class sınıf = Class.forName("com.cengfurkan.PrivateClass");
   Object object = sınıf.newInstance();
   Method[] metodlar = sınıf.getDeclaredMethods();
   for (int i = 0; i < metodlar.length; i++) {
    System.out.println("//// Metot Başlangıcı");
    System.out.println("Metod Adı: " + metodlar[i].getName());
    System.out.println("Metodun Geri Dönüş Tipi: "
      + metodlar[i].getReturnType());
    metodlar[i].setAccessible(true);
    System.out.println("Metodun Return Ettiği Değer: "
      + metodlar[i].invoke(object));
    System.out.println("// Metot Bitişi");
   }
  } catch (Exception e) {
   System.out.println("Hata: " + e.getMessage());
  }
 }
}
Karşımıza metodların adları, geri dönüş tipleri ve ne döndürdüğü çıkıyor.

Yazımı burada bitiriyorum. Bir sonraki yazıda görüşmek üzere.


1 yorum: