الreflection هي العملية التي يقوم فيها برنامج ما بالتعرف على بنية مكوناته الداخلية أثناء اشتغاله وإمكانية تغييرها
ماذا يعني هذا الكلام؟؟؟ :wacko:
لنفترض أنك وجدت في مكان ما بالصدفة ملفا تنفيديا ".class" إسمه MySuperPowerfullClass، فانتابك الفضول لمعرفة ماذا تحتوي الكلاس، لكنك ليس لديك الشيفرة، فما العمل؟؟ الreflection هي الحل.
ستقوم بكتابة برنامج، داخل هذا هذا البرنامج ستقوم بإنشاء كائن (object) من صنف MySuperPowerfullClass.
كما قلنا فإن الreflection تسمح بالتعرف على بنية مكونات البرنامج الداخلية، والكائن الذي أنشأناه الآن هو أحد مكونات البرنامج، يعني يمكننا معرفة بنيته
ملاحظة: في الجافا، ليس لدينا إمكانية تغيير مكونات البرنامج، القراءة هي المتوفرة فقط
عارف عارف، أنت تتحرق شوقا لمعرفة ماذا تفعل هذه الكلاس :lol: ، لذلك سأشرح الطريقة المتبعة
كل العمليات الخاصة بالreflection تمر عبر هذه الكلاس java.lang.Class. كل كلاس يتم استعماله في البرنامج فإن الJVM تقوم بإنشاء كائن من صنف Class يكون مرتبطا به. فكيف نصل إلى هذا الكائن؟؟؟
هناك ثلاث طرق:
الطريقة الأولى: إذا كنا قد عملنا initialization لمتغير من نفس صنف الكلاس، فيمكننا استعمال الميثود getClass()
Class classObject = mspc.getClass();
MySuperPowerfullClass mspc = new MySuperPowerfullClass();
لكن هذه الطريقة لن نستعملها لأننا لا نعرف إذا كانت الكلاس لديها constructor بدون arguments أو لا
الطريقة الثانية: سنستعمل في هذه الحالة .class
Class classObject = MySuperPowerfullClass.class;
الطريقة الثالثة: نستعمل Class.forName("fully-qualified name")
Class classObject = Class.getClass("MySuperPowerfullClass");الآن بعد حصلنا على object من صنف Class، سنبدأ عمليات البحث والتنقيب :lol:
ألآن، نريد معرفة الconstructor التي تحتوي عليها، بسيطة، نستعمل الميثود getDeclaredConstructors()، هذه الميثود تعيد مصفوفة من صنف Constructor تحتوي على جميع الconstructors
Constructor[] constructors = classObject.getDeclaredConstructors();
Class classObject = MySuperPowerfullClass.class;
الكلاس Constructor تمثل ... constructor طبعا :blink: . نريد معرفة كم يوجد من constructor، وما هي أصناف الparameters التي تنتظرها، هذا ممكن عن طريق الميثود getParameterTypes()، هذه الميثود تعيد مصفوفة من صنف Class. نحن نريد إسم الصنف وليس متغير من صنف Class، بسيطة بسيطة، نستعمل الميثود getName()
for (int i = 0; i < constructors.length; i++) {
System.out.println("Constructor number " + (i+1));
Class[] parameters = constructors.getParameterTypes();
if (parameters.length == 0)
System.out.println("No arguments");
for (int j = 0; j < parameters.length; j++) {
System.out.println("--------Constructor number " + (j+1) + " is " + parameters[j].getName());
}
}
System.out.println("This class has " + constructors.length + " constructors.");الآن نعرف الconstructors الموجودة في الكلاس، حان دور الmethods والattributes
لمعرفة الmethods، فالطريقة تشبه إلى حد ما الطريقة المتبعة بالنسبة للconstructors، الإختلاف فقط في الكلاس المستعملة وهي Method بدل Constructor، والميثود المستعملة getDeclaredMethods() بدل getDeclaredConstructors()
System.out.println("This class has " + methods.length + " methods.");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method number " + (i+1));
System.out.println("--------Name: " + methods.getName());
Class[] parameters = methods.getParameterTypes();
if (parameters.length == 0)
System.out.println("--------No arguments");
for (int j = 0; j < parameters.length; j++) {
System.out.println("--------Method parameter " + (j+1) + " is " + parameters[j].getName());
}
}
Method[] methods = classObject.getDeclaredMethods();
بقي لنا الآن التعرف على الattributes الخاصة بالكلاس، من أجل ذلك سنستعمل الميثود getDeclaredFields() التي تعيد لنا مصفوفة من صنف Field. هذه الكلاس تحتوي على الميثود getName() التي تعطينا إسم الattribute على شكل String، والميثود getType() والتي تعطينا صنف هذا الattribute على شكل object من صنف Class. وكما قلنا سابقا يمكننا معرفة إسم هذا الصنف عن طريق الميثود getName() الخاصة بClass
System.out.println("This class has " + fields.length + " fields.");
for (int i = 0; i < fields.length; i++) {
System.out.println("Field number " + (i+1));
System.out.println("--------Name: " + fields.getName());
System.out.println("--------Type: " + fields.getType().getName());
}
Field[] fields = classObject.getDeclaredFields();
إذا لم تفهم شيئا من هذا الكلام، وطبعا هذا راجع لموهبتي الخارقة في الشرح :lol: ، يمكنك زيارة هذا الرابط The Reflection API
هذه هي الكلاس التي استعملناها، طلعت لا هي super ولا powerfull :angry:
private String msg;
MySuperPowerfullClass() {
msg = "I'm a powerfull class, be aware!!!";
}
MySuperPowerfullClass(String msg) {
this.msg = msg;
}
public void sayHello() {
System.out.println("Hello");
}
public void sayBye() {
System.out.println("Bye");
}
public void sayMessage() {
System.out.println(msg);
}
public void saySomething(String str) {
System.out.println(str);
}
}
public class MySuperPowerfullClass {وهذا هو البرنامج الرائع الذي كتبته... من يتجرأ ويشكك في روعته :angry:
public class TestReflection {
public static void main(String[] args) {
//MySuperPowerfullClass mspc;
Class classObject = MySuperPowerfullClass.class;
Constructor[] constructors = classObject.getDeclaredConstructors();
System.out.println("This class has " + constructors.length + " constructors.");
for (int i = 0; i < constructors.length; i++) {
System.out.println("Constructor number " + (i+1));
Class[] parameters = constructors.getParameterTypes();
if (parameters.length == 0)
System.out.println("No arguments");
for (int j = 0; j < parameters.length; j++) {
System.out.println("--------Constructor parameter " + (j+1) + " is " + parameters[j].getName());
}
}
Field[] fields = classObject.getDeclaredFields();
System.out.println("This class has " + fields.length + " fields.");
for (int i = 0; i < fields.length; i++) {
System.out.println("Field number " + (i+1));
System.out.println("--------Name: " + fields.getName());
System.out.println("--------Type: " + fields.getType().getName());
}
Method[] methods = classObject.getDeclaredMethods();
System.out.println("This class has " + methods.length + " methods.");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method number " + (i+1));
System.out.println("--------Name: " + methods.getName());
Class[] parameters = methods.getParameterTypes();
if (parameters.length == 0)
System.out.println("--------No arguments");
for (int j = 0; j < parameters.length; j++) {
System.out.println("--------Method parameter " + (j+1) + " is " + parameters[j].getName());
}
}
}
}
import java.lang.reflect.*;
وأخيرا هذه مخارج البرنامج عند تنفيذه







