Bu Sayfayı Paylaş:

Kavram

Java Reflection API

Tanım: Java'da runtime'da (çalışma zamanı) class, interface, enum gibi yapılar hakkında bilgi (bir sınıfın methodları, bir method'un aldığı parametreler vb..) almayı sağlayan, bir sınıftan nesne yaratmayı, bir nesnenin method'larını çağırma, alanlarını değiştirme gibi işlevler sağlayan bir API. Gerekli sınıflar ve interface'ler java.lang.reflect paketinde bulunmaktadır.

Veri

Class Tipinde Bir Nesne Yaratan Örnek

Class tipinde bir nesne yaratılması üç yöntemle olmaktadır ve aşağıdaki örnekte bu üç yöntem kullanılmaktadır:
package com.test.reflection;

public class ClassTest {
	
	public static void main(String[] args) {
		
		Class<?> classPerson=Person.class;
		
		Person person=new Person();
		Class<?> classPerson2=person.getClass();
		
		Class classPerson3=null;
		try {
			classPerson3=Class.forName("com.test.reflection.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		System.out.println(classPerson.getName());
		System.out.println(classPerson2.getName());
		System.out.println(classPerson3.getName());
		
	}

}
İlk yöntem Person.class şeklinde static class alanını kullanmaktadır. İkinci yöntem yaratılan bir nesneden person.getClass() ile Class'ını almaktadır. Üçüncü yöntem ise bir String'ten Class.forName("com.test.reflection.Person") şeklinde Class üretmektir. Bu üç yöntemle elde edilen Class örneğinden Person sınıfı ile ilgili istenilen bilgiler alınabilir. Yukarıdaki uygulama çalıştığında com.test.reflection.Person com.test.reflection.Person com.test.reflection.Person şeklinde Person sınıfın adı basılacaktır.

Örnek

Bir Sınıfın Alan , Method ve Kurucu Bilgilerinin Bulunması

Aşağıdaki örnekte bir Person sınıfının alanları , method'ları ve kurucularının bilgileri ekrana basılmıştır. Person sınıfı aşağıdaki gibidir :
package com.test.reflection;
public class Person {
	
	private String name;
	private double weight;
	public int year;
		
	public Person() {
	}
	
	public Person(String name) {
		this.name=name;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	
	public String getNameAndYear(){
		return name + "-" + year;
	}
}
Örnek uygulama aşağıdaki gibidir :
package com.test.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class ClassGetInfoTest {
	
	public static void main(String[] args) {
		
		Person person=new Person();
		person.setName("Refik Başaran");
		person.setWeight(90);
		person.setYear(1950);
		
		Class<?> classOfPerson=person.getClass();
		
		System.out.println("name:"+classOfPerson.getName());
		
		System.out.println("");
		
		System.out.println("fields:");
		
		for (Field field : classOfPerson.getFields()) {
		
			System.out.println("field name: "+field.getName() +
					"- field type name: "+field.getType().getName());
		}
				
		System.out.println("methods:");
		
		for (Method method : classOfPerson.getMethods()) {
			
			System.out.println("method name: "+method.getName());
			
			System.out.println("method parameter count: "+method.getParameterCount());
			
			for(Parameter parameter: method.getParameters()){
				System.out.println("field name: "+parameter.getName() + 
						" - field type name: "+parameter.getType().getName());				
			}
			
			System.out.println("return type:"+ method.getReturnType().getName());
			
			System.out.println("*");
		}
		
		System.out.println("constructors: ");
		
		for (Constructor constructor : classOfPerson.getConstructors()) {
			
			System.out.println("constructor parameter count: "+constructor.getParameterCount());
			
			for(Parameter parameter: constructor.getParameters()){
				System.out.println("constructor parameter name: "+parameter.getName() + 
						" - constructor parameter type name: "+parameter.getType().getName());				
			}
			
		}
		
		
	}
}

İlk önce bir Person nesnesi yaratıyoruz. person.getClass(); ile Class bilgisini alıp class adını bastırıyoruz. classOfPerson.getFields() ile alanlarını alıyoruz (public alanlar gelecektir) ve adlarını ve tiplerini bastırıyoruz. classOfPerson.getMethods() ile methodlarını ve ardından classOfPerson.getConstructors() ile de kurucularını alıp ekrana bastırıyoruz. Uygulamayı çalıştırdığımızda aşağıdaki gibi çıktı oluşacaktır :

name:com.test.reflection.Person
fields:
field name: year - field type name: int
methods:
method name: getName
method parameter count: 0
return type:java.lang.String
*
method name: setName
method parameter count: 1
field name: arg0 - field type name: java.lang.String
return type:void
*
method name: setWeight
method parameter count: 1
field name: arg0 - field type name: double
return type:void
*
method name: getWeight
method parameter count: 0
return type:double
*
method name: getNameAndYear
method parameter count: 0
return type:java.lang.String
*
method name: getYear
method parameter count: 0
return type:int
*
method name: setYear
method parameter count: 1
field name: arg0 - field type name: int
return type:void
*
method name: wait
method parameter count: 2
field name: arg0 - field type name: long
field name: arg1 - field type name: int
return type:void
*
method name: wait
method parameter count: 1
field name: arg0 - field type name: long
return type:void
*
method name: wait
method parameter count: 0
return type:void
*
method name: equals
method parameter count: 1
field name: arg0 - field type name: java.lang.Object
return type:boolean
*
method name: toString
method parameter count: 0
return type:java.lang.String
*
method name: hashCode
method parameter count: 0
return type:int
*
method name: getClass
method parameter count: 0
return type:java.lang.Class
*
method name: notify
method parameter count: 0
return type:void
*
method name: notifyAll
method parameter count: 0
return type:void
*
constructors:
constructor parameter count: 0
constructor parameter count: 1
constructor parameter name: arg0 - constructor parameter type name: java.lang.String

Dikkat edilirse Object sınıfında bulunan method'larda çıktıda gözükmektedir.

Örnek

Bir Sınıfın Örneğin Yaratılım Method'larını Çağıran Örnek

Aşağıdaki örnekte bir Person sınıfının nesnesi yaratılmakta ve method'ları çağrılmaktadır. Person sınıfı aşağıdaki gibidir:
package com.test.reflection;

public class Person {
	
	private String name;
	private double weight;
	public int year;
		
	public Person() {
	}
	
	public Person(String name) {
		this.name=name;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	
	public String getNameAndYear(){
		return name + "-" + year;
	}

}
Örnek uygulama aşağıdaki gibidir :
package com.test.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ClassSetInfoTest {
	
	public static void main(String[] args) 
			throws ClassNotFoundException, NoSuchMethodException, 
			SecurityException, InstantiationException,
			IllegalAccessException, 
			IllegalArgumentException, 
			InvocationTargetException {
	
		Class<?> classOfPerson=Class.forName("com.test.reflection.Person");
		
		Constructor constructor=classOfPerson.getConstructor(String.class);
		
		Object objectOfPerson=constructor.newInstance("Neşet Ertaş");
		
		Method methodOfPersonSetYear = objectOfPerson.getClass().getMethod("setYear", int.class);
		methodOfPersonSetYear.invoke(objectOfPerson, 65);
		
		Method methodOfPerson = objectOfPerson.getClass().getMethod("getNameAndYear", null);
		String response=(String)methodOfPerson.invoke(objectOfPerson, null);
		
		System.out.println("response: "+response);
		
		
	}

}

İlk önce Class.forName("com.test.reflection.Person") ile bir Class nesnesi yaratılmıştır. classOfPerson.getConstructor(String.class) ile String kabul eden kurucusu alınmıştır. constructor.newInstance("Neşet Ertaş") diyerek bu kurucu ile bir instance (örnek) yaratılmıştır. objectOfPerson.getClass().getMethod("setYear", int.class) ile setYear method'u alınmış ve methodOfPersonSetYear.invoke(objectOfPerson, 65) ile çağrılmıştır. Aynı şekilde getNameAndYear method'u da alınmış ve çağrılmıştır. getNameAndYear geri değer döndürmesinden dolayı geri dönen değer alınmış ve ekranda bastırılmıştır. Uygulama çalıştığında aşağıdaki bilgi basılacaktır: response: Neşet Ertaş-65 Uygulama çok sayıda Exception fırlattığına dikkat ediniz.

İpucu

Reflection APIsi ile Inner Class'ın Constructor'un Elde Edilmesi

Java'da refelection API ise ile public olmayan kurucuları da getDeclaredConstructor(..) yöntemi ile alınmaktadır. Aşağıda bir outer ve içinde de bir inner sınıf örneği görülmektedir:
public class OuterTest{
	public class InnerTest{
		InnerTest(String test){
			System.out.println(test);
		}
	}
}
InnerTest sınıfının kurucusunu reflection ile aşağıdaki gibi alabiliriz ve instance'nı yaratabiliriz :
Class enclosingClass = Class.forName("com.fibiler.test.OuterTest");
Object enclosingInstance = enclosingClass.newInstance();
Class innerClass = Class.forName("com.fibiler.test.OuterTest$InnerTest");
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass,String.class);
Object innerInstance = ctor.newInstance(enclosingInstance,"test");
Dikkat edilirse getDeclaredConstructor() yöntemine outer sınıfı, Class olarak verilmektedir. Instance yaratırken (newInstance) ise outer sınıfının nesnesi ilk parametre olarak verilmektedir. Bu durum InnerTest sınıfının başka bir sınıfın içinde bulunan bir sınıf olmasından kaynaklanmaktadır. Örneğin inner class olmayan OuterTest sınıfının kurucusunu ve instance'nı aşağıdaki gibi yaratabiliriz :
Class enclosingClass = Class.forName("com.fibiler.test.OuterTest");
Constructor<?> outerCounstuctor = enclosingClass.getDeclaredConstructor();
Object outerInstance = outerCounstuctor.newInstance();

Görüldüğü gibi getDeclaredConstructor ve newInstance method'ları herhangi bir outer sınıfı olmadığı için fazladan parametre almamaktadır.



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