الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ما هي الreflection وما فائدتها؟؟

بدأه herch في 10 سبتمبر 2009 · 21 رد · 3,459 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

ال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.*;

وأخيرا هذه مخارج البرنامج عند تنفيذه

outputc.png

3
#2

جميل جميل جداً,

لدي بعض الأسئلة و لكن بعد أن أقرأ الموضوع جيداً :)

#3

ربنا يستر :angry:

#4

حبة حبة علينا أصلنا مش ولا بد في Java :angry:

اقتباس
وما هي أصناف الparameters التي تنتظرها، هذا ممكن عن طريق الميثود getParameterTypes()، هذه الميثود تعيد مصفوفة من صنف Class.

ممكن تعطينا فكرة مختصرة عن Class. و كيف تعاملها Java, و هل ينطبق الكلام الذي قلته عن الـ Primitive-Types, هل لهم Class أيضاً ؟

سمعت عن Groovy و سمعت أنها تعمل فوق JVM, و هي لغة Dynamic Typing, هل تسمح بتعديل بنية الـ Classes كما في Smalltalk و Objective-C على سبيل المثال؟

تحياتي....

#5

الكلاس Class هي كلاس تمثل كلاس :P

كما قلت، كل كلاس مستعمل في برنامجك ستقوم الJVM بإنشاء instance من صنف Class تحتوي على كل المعلومات التي لها علاقة ببنية هذه الكلاس، الmethods والattributes التي تحتوي عليها، الكلاس التي ترث منها...

ولماذا إنشاء instance من صنف Class؟؟ ما الحاجة لها؟؟ حتى نتمكن من استعمال الreflection

الprimitive-types لها أيضا instance من Class مرتبط بها، لكنه لا يحتوي على معلومات تذكر، لأن الprimitive-types حالة خاصة في الجافا، ولكني لا أعلم بالضبط خصوصيتها :P

مثلا هذا الكود


Constructor[] constructors = classObject.getDeclaredConstructors();
System.out.println("This class has " + constructors.length + " constructors.");
Field[] fields = classObject.getDeclaredFields();
System.out.println("This class has " + fields.length + " fields.");
Method[] methods = classObject.getDeclaredMethods();
System.out.println("This class has " + methods.length + " methods.");
Class classObject = boolean.class;

سيعطي النتيجة التالية

اقتباس
This class has 0 constructors.

This class has 0 fields.

This class has 0 methods.

بالنسبة لتعديل بنية الكلاس فقد قلت بأن الجافا تسمح فقط بالقراءة وليس التعديل -_-

بالنسبة لGroovy وهل يسمح بتعديل بنية الكلاس، فشخصيا لا أظن ذلك مع أني لا علم لي بGroovy، لكن بما أنها تقوم بتحويل الكود إلى byte-code يعمل على JVM، فهي تبقى محدودة بما تتيحة الJVM، وهذه الأخيرة لا تتيح تعديل بنية الكلاس على حسب اعتفادي

تم تعديل هذه المشاركة بواسطة herch في 10 سبتمبر 2009 في 03:37

#6

يعني حسب ما فهمت انو نحنا بنحصل على العدد او الية تنظيم الكود داخل الكلاس

ممممممم

صح فهمي ولا بدو تصحيح ؟ :happy:

بالتوفيق

الله معك

1
#7

جزاك الله خيرا أخ Herch

يبدو من الsnapeshot أنك تستخدم debian :lol:

#8

الreflection تتيح الحصول على بنية الكلاس، يعني الmethods و الattributes التي تحتوي عليها، الكلاس التي ترث منها، الinterfaces التي تعمل لها implmentation ....

لكنها لا تسمح بمعرفة الكود الموجود داخل الmethods أو الconstructor، لأن قراءة الكود حكاية أخرى، فذلك يتم بقراءة الملف class مباشرة واستخراج الكود منه، لكن هذا الكود يكون على شكل JVM instructions

نعم يا أخ هويدي، أستعمل debian lenny :P

#9

تسلم ايديك اخ herch موضوع حلو كثير ورائع وطريقة الشرح رائعه ايضا :)

ab66i830gh93.gif

i25sctz8qnls.jpg

#10

شكرا أخي عصام ,, معلومات جديدة و مفيدة

#11

على فكرة ممكن أيضاً أن تستخدم reflection في عملية إنشاء الكائنات

وعملية مناداة الدوال

هذا مثال على الموضوع

// With reflection
Class cls = Class.forName("Foo");
Object foo = cls.newInstance();
Method method = cls.getMethod("hello", null);
method.invoke(foo, null);

هذا الموضوع مفيد جداً

ويمكن استغلاله بطرق مختلفة

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#12
Constructor[] constructors = classObject.getDeclaredConstructors();

كلاس غريب بصراحة :D

ولكن اللي فهمته من الموضوع .. أن كل ملفات .class يمكن بسهولة اعادتها الى أصلها .. باستخدام reflection .. لايوجد شيء مغلق المصدر

شكرا لك .. كان عندي التباس من المقصود بالكلاس Class وفائدته

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#13
herch كتب:

الreflection تتيح الحصول على بنية الكلاس، يعني الmethods و الattributes التي تحتوي عليها، الكلاس التي ترث منها، الinterfaces التي تعمل لها implmentation ....

لكنها لا تسمح بمعرفة الكود الموجود داخل الmethods أو الconstructor، لأن قراءة الكود حكاية أخرى، فذلك يتم بقراءة الملف class مباشرة واستخراج الكود منه، لكن هذا الكود يكون على شكل JVM instructions

#14

السلام عليكم ورحمة الله وبركاته

كل عام وانتم بخير وشهر مبارك للجميع

اشكر الاخ herch على هذه المعلومات القيمة والشرح الدقيق واشكر ايضا كل من اسهم في اثراء هذا الموضوع

ولكن لدي تساؤول عن كيفية الحصول على method source code اقصد اني اريد اقرأ من file واكتب محتواه في آخر ثم عند مروري بobject ينادي method من الفايل الذي اقراه اريد اذهب لهذه method اقراها واكتب محتواها مع بعض التغييرات الى الملف الاخر

وكنت اظن ان reflection ممكن يساعدني في هذا الامر لكن حسب الشرح فهمت انه reflection يعطي اسم الclass و methods وليس المحتوى ، واحتاج المساعدة في هذا الامر وهل java.lang.instrument واقصد بالذات ,Class ClassDefinition ممكن ان تساعدني حيث انها ترجع الكلاس

شاكرة مقدما كل من ساعدني في هذا الامر

#15

شكرا الك اخوي المحبوب ... عنجد شي حلو ، بس للأسف ما اشتغلت معاي :dry: :mad: :wacko:

جربت نقل كود الكلاس MySuperPowerfullClass في ملف تحت اسم MySuperPowerfullClass.class ووضعه في الpackage مع الكود TestReflection.java لكنه بيطلعلي اخطاء :blink: .. جربت حتى وضع الكلاس في مجلد الBin حق الكلاسات .. لكن ولا شي :huh: :huh:

بارك الله فيكم أي واحد بيعرف الحل لا يبخل علينا :dry: ... تراني اكتفيت من النزعات الجفاوية :happy: :happy: :haha:

شكرا لكم :lol:

556891961.gif

I am learning from you

it is the programmer eye

#16

لم تذكر الأخطاء التي تعاني منها

فكيف لنا أن نساعدك

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#17
علاء الصالحي كتب:

لم تذكر الأخطاء التي تعاني منها

فكيف لنا أن نساعدك

تحياتي

هلأ الخطوات اللي عملتها صح ؟؟؟

المشكلة في MySuperPowerfullClass حم يتاخذها Error مع اني واضعها مع TestReflection.java وواضعها كمان في مجلد الBin

Class classObject = MySuperPowerfullClass.class;

.... أرجو توضيح وتدقيق الخطوات .. شكلي غلطان على ما اعتقد :dry:

شكرا لكم :happy: :happy: :happy:

556891961.gif

I am learning from you

it is the programmer eye

#18

لم أفهم ما المشكلة بالضبط

المثال مرفق على شكل مشروع netbeans، ممكن يعمل

reflection.zip

تم تعديل هذه المشاركة بواسطة herch في 16 مايو 2012 في 19:22

#19
herch كتب:

لم أفهم ما المشكلة بالضبط

المثال مرفق على شكل مشروع netbeans، ممكن يعمل

فهمت حسب ما قلت أنت : أنو لما اعثر على ملف تنفيذي بتاع الجافا مثلا mySuperPowerfullClass.class فانني استطيع استعمالها مع كلاس معينة مثلا TestReflection.java اين يتم عمل call للMySuperPowerfullClass.class

الreflection هي العملية التي يقوم فيها برنامج ما بالتعرف على بنية مكوناته الداخلية أثناء اشتغاله وإمكانية تغييرها
ماذا يعني هذا الكلام؟؟؟ :wacko:
لنفترض أنك وجدت في مكان ما بالصدفة ملفا تنفيديا ".class" إسمه MySuperPowerfullClass، فانتابك الفضول لمعرفة ماذا تحتوي الكلاس، لكنك ليس لديك الشيفرة، فما العمل؟؟ الreflection هي الحل.
ستقوم بكتابة برنامج، داخل هذا هذا البرنامج ستقوم بإنشاء كائن (object) من صنف MySuperPowerfullClass.
كما قلنا فإن الreflection تسمح بالتعرف على بنية مكونات البرنامج الداخلية، والكائن الذي أنشأناه الآن هو أحد مكونات البرنامج، يعني يمكننا معرفة بنيته

لكنك في الكود المرفق ، أرفقت TestReflection.java مع MySuperPowerfullClass.java ... فما فائدة اضافة MySuperPowerfullClass.java علما انني فهمت انني استطيع استعمال MySuperPowerfullClass.class ...... وماذا اذا وجدت اكواد ذات امتداد .class

بصورة مختصرة، اذا وجدت كود بامتداد .class كيف يمكنني رؤية ما في داخله ؟ وكيف يمكنني استعماله مع كلاسات أخرى ذات امتداد .java .... أريد ان اطبق جوهر هاد الموضوع :lol:

شكرا لكم

556891961.gif

I am learning from you

it is the programmer eye

#20

ال reflection لا تتيح لك معرفة الكود المصدري للكلاس، فقط الهيكل structure. هذا مذكور في الموضوع.

ما تريده ستجده في ال decompiler، مثلا http://java.decompiler.free.fr/

1
#21
herch كتب:

ال reflection لا تتيح لك معرفة الكود المصدري للكلاس، فقط الهيكل structure. هذا مذكور في الموضوع.

ما تريده ستجده في ال decompiler، مثلا http://java.decompiler.free.fr/

أنا آسف أخوي ربما ما عرفت كيف اشرح مشكلتي :dry: :blink: :lol: ... كل مافي الامر اني اريد ان اعرف كيف استطيع استعمال كلاسات بامتداد .class مع اكواد جافا .java .. ... لا اريد معرفة الكود بتاع .class ولا اريد عمل decompiler له ... وانما اريد ان اجرب طريقة شرحك

من فضلك أخوي .. طلب أخير ، هلا تعيد الشرح حبة حبة مع مثال بسيييط جدا

انا اسف على الازعاج ... تقبل تحياتي الخالصة :happy: :happy:

556891961.gif

I am learning from you

it is the programmer eye

مواضيع مشابهة