سؤال

ما هو الانعكاس ولماذا هو مفيد؟

أنا مهتم بشكل خاص بجافا، لكني أفترض أن المبادئ هي نفسها في أي لغة.

هل كانت مفيدة؟

المحلول

يتم استخدام انعكاس الاسم لوصف التعليمات البرمجية القادرة على فحص التعليمات البرمجية الأخرى في نفس النظام (أو نفسه).

على سبيل المثال، لنفترض أن لديك كائنًا من نوع غير معروف في Java، وترغب في استدعاء أسلوب "doSomething" عليه إذا كان موجودًا.نظام الكتابة الثابتة في Java ليس مصممًا حقًا لدعم هذا ما لم يتوافق الكائن مع واجهة معروفة، ولكن باستخدام الانعكاس، يمكن للتعليمات البرمجية الخاصة بك النظر إلى الكائن ومعرفة ما إذا كان لديه طريقة تسمى "doSomething" ثم الاتصال به إذا كنت اريد ان.

لذا، لإعطائك مثالًا برمجيًا لذلك في Java (تخيل أن الكائن المعني هو foo):

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

إحدى حالات الاستخدام الشائعة جدًا في Java هي الاستخدام مع التعليقات التوضيحية.على سبيل المثال، ستستخدم JUnit 4 الانعكاس للبحث في فصولك عن الأساليب الموسومة بالتعليق التوضيحيTest، ثم ستستدعيها عند تشغيل اختبار الوحدة.

هناك بعض الأمثلة الجيدة للتفكير لتبدأ بها http://docs.Oracle.com/javase/tutorial/reflect/index.html

وأخيرًا، نعم، المفاهيم متشابهة إلى حد كبير في اللغات الثابتة الأخرى التي تدعم الانعكاس (مثل C#).في اللغات المكتوبة ديناميكيًا، تكون حالة الاستخدام الموصوفة أعلاه أقل أهمية (نظرًا لأن المترجم سيسمح باستدعاء أي أسلوب على أي كائن، ويفشل في وقت التشغيل إذا لم يكن موجودًا)، ولكن الحالة الثانية هي البحث عن الأساليب التي تم وضع علامة عليها أو العمل بطريقة معينة لا يزال شائعا.

تحديث من تعليق:

القدرة على فحص الكود في النظام ورؤية أنواع الكائنات ليست انعكاسًا ، بل تكتب التأمل.الانعكاس هو القدرة على إجراء تعديلات في وقت التشغيل من خلال الاستفادة من التأمل.التمييز ضروري هنا لأن بعض اللغات تدعم التأمل ، ولكن لا تدعم التفكير.أحد الأمثلة على ذلك هو C ++

نصائح أخرى

انعكاس هي قدرة اللغة على فحص واستدعاء الفئات والأساليب والسمات وما إلى ذلك ديناميكيًا.في وقت التشغيل.

على سبيل المثال، جميع الكائنات في Java لها الطريقة getClass(), ، والذي يتيح لك تحديد فئة الكائن حتى لو كنت لا تعرفه في وقت الترجمة (على سبيل المثال.إذا أعلنت أنها Object) - قد يبدو هذا تافهاً، لكن مثل هذا التفكير غير ممكن في اللغات الأقل ديناميكية مثل C++.تتيح لك الاستخدامات الأكثر تقدمًا سرد واستدعاء الأساليب والمنشئات وما إلى ذلك.

الانعكاس مهم لأنه يتيح لك كتابة برامج لا تحتاج إلى "معرفة" كل شيء في وقت الترجمة، مما يجعلها أكثر ديناميكية، حيث يمكن ربطها معًا في وقت التشغيل.يمكن كتابة التعليمات البرمجية مقابل واجهات معروفة، ولكن يمكن إنشاء مثيل للفئات الفعلية التي سيتم استخدامها باستخدام الانعكاس من ملفات التكوين.

تستخدم الكثير من الأطر الحديثة التفكير على نطاق واسع لهذا السبب بالذات.تستخدم معظم اللغات الحديثة الأخرى الانعكاس أيضًا، وفي لغات البرمجة النصية (مثل بايثون) تكون أكثر تكاملاً، حيث يبدو الأمر أكثر طبيعية ضمن نموذج البرمجة العام لتلك اللغات.

إحدى استخداماتي المفضلة للانعكاس هي طريقة تفريغ Java أدناه.يأخذ أي كائن كمعلمة ويستخدم واجهة برمجة تطبيقات انعكاس Java لطباعة كل اسم وقيمة حقل.

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
    callCount++;
    StringBuffer tabs = new StringBuffer();
    for (int k = 0; k < callCount; k++) {
        tabs.append("\t");
    }
    StringBuffer buffer = new StringBuffer();
    Class oClass = o.getClass();
    if (oClass.isArray()) {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("[");
        for (int i = 0; i < Array.getLength(o); i++) {
            if (i < 0)
                buffer.append(",");
            Object value = Array.get(o, i);
            if (value.getClass().isPrimitive() ||
                    value.getClass() == java.lang.Long.class ||
                    value.getClass() == java.lang.String.class ||
                    value.getClass() == java.lang.Integer.class ||
                    value.getClass() == java.lang.Boolean.class
                    ) {
                buffer.append(value);
            } else {
                buffer.append(dump(value, callCount));
            }
        }
        buffer.append(tabs.toString());
        buffer.append("]\n");
    } else {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("{\n");
        while (oClass != null) {
            Field[] fields = oClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                buffer.append(tabs.toString());
                fields[i].setAccessible(true);
                buffer.append(fields[i].getName());
                buffer.append("=");
                try {
                    Object value = fields[i].get(o);
                    if (value != null) {
                        if (value.getClass().isPrimitive() ||
                                value.getClass() == java.lang.Long.class ||
                                value.getClass() == java.lang.String.class ||
                                value.getClass() == java.lang.Integer.class ||
                                value.getClass() == java.lang.Boolean.class
                                ) {
                            buffer.append(value);
                        } else {
                            buffer.append(dump(value, callCount));
                        }
                    }
                } catch (IllegalAccessException e) {
                    buffer.append(e.getMessage());
                }
                buffer.append("\n");
            }
            oClass = oClass.getSuperclass();
        }
        buffer.append(tabs.toString());
        buffer.append("}\n");
    }
    return buffer.toString();
}

استخدامات الانعكاس

يتم استخدام الانعكاس بشكل شائع بواسطة البرامج التي تتطلب القدرة على فحص أو تعديل سلوك وقت التشغيل للتطبيقات التي تعمل في جهاز Java الظاهري.هذه ميزة متقدمة نسبيًا ويجب استخدامها فقط من قبل المطورين الذين لديهم فهم قوي لأساسيات اللغة.مع أخذ هذا التحذير في الاعتبار، يعد الانعكاس أسلوبًا قويًا ويمكنه تمكين التطبيقات من تنفيذ عمليات قد تكون مستحيلة.

ميزات القابلية للتوسعة

قد يستفيد التطبيق من الفئات الخارجية المعرفة من قبل المستخدم عن طريق إنشاء مثيلات كائنات قابلة للتوسعة باستخدام أسمائها المؤهلة بالكامل.متصفحات الفصل وبيئات التطوير البصري ، يجب أن يكون متصفح الفصل قادرًا على تعداد أعضاء الفصول.يمكن لبيئات التطوير المرئية الاستفادة من الاستفادة من معلومات النوع المتوفرة في الانعكاس لمساعدة المطور في كتابة التعليمات البرمجية الصحيحة.يجب أن يكون أصحاب الأخطاء وأدوات الاختبار قادرين على فحص الأعضاء الخاصين في الفصول الدراسية.يمكن لأدوات الاختبار الاستفادة من الانعكاس لاستدعاء مجموعة واجهات برمجة التطبيقات (APIs) القابلة للاكتشاف والمحددة في فئة ما بشكل منهجي، لضمان مستوى عالٍ من تغطية التعليمات البرمجية في مجموعة الاختبار.

عيوب الانعكاس

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

  • الأداء العام

نظرًا لأن الانعكاس يشتمل على أنواع تم حلها ديناميكيًا، فلا يمكن تنفيذ بعض تحسينات جهاز Java الظاهري.وبالتالي، فإن العمليات العاكسة لها أداء أبطأ من نظيراتها غير العاكسة ويجب تجنبها في أقسام التعليمات البرمجية التي يتم استدعاؤها بشكل متكرر في التطبيقات الحساسة للأداء.

  • القيود الأمنية

يتطلب الانعكاس إذنًا في وقت التشغيل قد لا يكون موجودًا عند التشغيل تحت مدير الأمان.يعد هذا أحد الاعتبارات المهمة للتعليمات البرمجية التي يجب تشغيلها في سياق أمان مقيد، كما هو الحال في التطبيق الصغير.

  • التعرض للداخلية

نظرًا لأن الانعكاس يسمح للتعليمات البرمجية بتنفيذ عمليات قد تكون غير قانونية في التعليمات البرمجية غير العاكسة، مثل الوصول إلى الحقول والأساليب الخاصة، فإن استخدام الانعكاس يمكن أن يؤدي إلى آثار جانبية غير متوقعة، مما قد يؤدي إلى خلل في التعليمات البرمجية وقد يدمر قابلية النقل.يكسر الكود الانعكاسي التجريدات وبالتالي قد يغير السلوك مع ترقيات النظام الأساسي.

مصدر: واجهة برمجة التطبيقات للانعكاس

يعد الانعكاس آلية أساسية للسماح للتطبيق أو إطار العمل بالعمل مع التعليمات البرمجية التي ربما لم تتم كتابتها بعد!

خذ على سبيل المثال ملف web.xml النموذجي الخاص بك.سيحتوي هذا على قائمة بعناصر servlet، والتي تحتوي على عناصر فئة servlet المتداخلة.ستقوم حاوية servlet بمعالجة ملف web.xml، وإنشاء مثيل جديد لكل فئة servlet من خلال الانعكاس.

مثال آخر سيكون Java API لتحليل XML (جاكسب).حيث يتم "توصيل" موفر محلل XML عبر خصائص النظام المعروفة، والتي تُستخدم لإنشاء مثيلات جديدة من خلال الانعكاس.

وأخيرا، المثال الأكثر شمولا هو ربيع الذي يستخدم الانعكاس لإنشاء حبوبه، ولاستخدامه المكثف للوكلاء

ليست كل لغة تدعم التفكير ولكن المبادئ عادة ما تكون هي نفسها في اللغات التي تدعمه.

الانعكاس هو القدرة على "التأمل" في بنية برنامجك.أو أكثر ملموسة.لإلقاء نظرة على الكائنات والفئات الموجودة لديك والحصول برمجيًا على معلومات حول الأساليب والحقول والواجهات التي تنفذها.يمكنك أيضًا الاطلاع على أشياء مثل التعليقات التوضيحية.

إنه مفيد في الكثير من المواقف.في كل مكان تريد أن تكون قادرًا على توصيل الفئات ديناميكيًا في التعليمات البرمجية الخاصة بك.يستخدم الكثير من مصممي الخرائط العلائقية للكائنات الانعكاس ليتمكنوا من إنشاء كائنات من قواعد البيانات دون معرفة الكائنات التي سيستخدمونها مسبقًا.تعتبر بنيات المكونات الإضافية مكانًا آخر يكون فيه التفكير مفيدًا.إن القدرة على تحميل التعليمات البرمجية ديناميكيًا وتحديد ما إذا كانت هناك أنواع تنفذ الواجهة الصحيحة لاستخدامها كمكون إضافي أمر مهم في تلك المواقف.

يسمح الانعكاس بإنشاء كائنات جديدة، واستدعاء الأساليب، وعمليات الحصول/الضبط على متغيرات الفئة ديناميكيًا في وقت التشغيل دون الحاجة إلى معرفة مسبقة بتنفيذها.

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");

في المثال أعلاه، المعلمة الخالية هي الكائن الذي تريد استدعاء الطريقة عليه.إذا كانت الطريقة ثابتة، فإنك تقدم قيمة فارغة.إذا لم تكن الطريقة ثابتة، فستحتاج أثناء الاستدعاء إلى توفير نسخة MyObject صالحة بدلاً من null.

يسمح لك الانعكاس أيضًا بالوصول إلى الأعضاء/الأساليب الخاصة بالفصل:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}

.

A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);
  • لفحص الفئات (المعروف أيضًا باسم الاستبطان) لا تحتاج إلى استيراد حزمة الانعكاس (java.lang.reflect).يمكن الوصول إلى البيانات التعريفية للفئة من خلال java.lang.Class.

يعتبر Reflection واجهة برمجة تطبيقات قوية جدًا ولكنها قد تؤدي إلى إبطاء التطبيق إذا تم استخدامها بشكل زائد، حيث إنها تحل جميع الأنواع في وقت التشغيل.

مثال :
خذ على سبيل المثال تطبيقًا بعيدًا يمنح تطبيقك كائنًا تحصل عليه باستخدام أساليب API الخاصة به.الآن استنادًا إلى الكائن، قد تحتاج إلى إجراء نوع من العمليات الحسابية.
يضمن الموفر أن الكائن يمكن أن يكون من 3 أنواع ونحتاج إلى إجراء عملية حسابية بناءً على نوع الكائن.
لذلك قد نقوم بالتنفيذ في 3 فئات تحتوي كل منها على منطق مختلف. من الواضح أن معلومات الكائن متاحة في وقت التشغيل لذا لا يمكنك إجراء تعليمات برمجية ثابتة لإجراء الحساب، ومن ثم يتم استخدام الانعكاس لإنشاء كائن من الفئة التي تحتاجها لإجراء الحساب بناءً على الكائن المستلم من الموفر.

يعد Java Reflection قويًا جدًا ويمكن أن يكون مفيدًا جدًا.انعكاس جافا يجعل من الممكن لفحص الفئات والواجهات والحقول والأساليب في وقت التشغيل، دون معرفة أسماء الفئات والأساليب وما إلى ذلك.في وقت التجميع.ومن الممكن أيضا أن إنشاء كائنات جديدة واستدعاء الأساليب والحصول على/تعيين قيم الحقول باستخدام الانعكاس.

مثال سريع لانعكاس Java يوضح لك كيف يبدو استخدام الانعكاس:

Method[] methods = MyObject.class.getMethods();

    for(Method method : methods){
        System.out.println("method = " + method.getName());
    }

يحصل هذا المثال على كائن Class من فئة تسمى MyObject.باستخدام كائن الفئة، يحصل المثال على قائمة بالطرق الموجودة في تلك الفئة، ويكرر الأساليب ويطبع أسمائها.

بالضبط كيف يعمل كل هذا موضح هنا

يحرر:بعد ما يقرب من عام واحد، أقوم بتحرير هذه الإجابة أثناء القراءة عن الانعكاس، حصلت على عدد قليل من الاستخدامات للانعكاس.

  • يستخدم Spring تكوين الفول مثل:


<bean id="someID" class="com.example.Foo">
    <property name="someField" value="someValue" />
</bean>

عندما يعالج سياق الربيع عنصر <bean> هذا، فإنه سيستخدم Class.forName(String) مع الوسيطة "com.example.Foo" لإنشاء مثيل لتلك الفئة.

سيستخدم الانعكاس مرة أخرى للحصول على أداة الضبط المناسبة لعنصر <property> وتعيين قيمته على القيمة المحددة.

  • يستخدم Junit الانعكاس خصيصًا لاختبار الأساليب الخاصة/المحمية.

بالنسبة للطرق الخاصة

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

بالنسبة للمجالات الخاصة

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

حسب فهمي:

يسمح الانعكاس للمبرمج بالوصول إلى الكيانات الموجودة في البرنامج ديناميكيًا.أي.أثناء ترميز تطبيق ما، إذا لم يكن المبرمج على علم بفئة ما أو أساليبها، فيمكنه الاستفادة من هذه الفئة ديناميكيًا (في وقت التشغيل) باستخدام الانعكاس.

يتم استخدامه بشكل متكرر في السيناريوهات التي يتغير فيها اسم الفئة بشكل متكرر.إذا نشأ مثل هذا الموقف، فمن الصعب على المبرمج إعادة كتابة التطبيق وتغيير اسم الفئة مرارًا وتكرارًا.

بدلاً من ذلك، باستخدام الانعكاس، هناك حاجة للقلق بشأن احتمال تغيير اسم الفئة.

انعكاس هي واجهة برمجة التطبيقات (API) التي تُستخدم لفحص أو تعديل سلوك الأساليب والفئات والواجهات في وقت التشغيل.

  1. يتم توفير الفئات المطلوبة للتفكير تحت java.lang.reflect package.
  2. يعطينا الانعكاس معلومات حول الفئة التي ينتمي إليها الكائن وأيضًا طرق تلك الفئة التي يمكن تنفيذها باستخدام الكائن.
  3. من خلال الانعكاس يمكننا استدعاء الأساليب في وقت التشغيل بغض النظر عن محدد الوصول المستخدم معها.

ال java.lang و java.lang.reflect توفر الحزم فئات لانعكاس جافا.

انعكاس يمكن استخدامها للحصول على معلومات حول -

  1. فصل ال getClass() يتم استخدام الطريقة للحصول على اسم الفئة التي ينتمي إليها الكائن.

  2. البنائين ال getConstructors() يتم استخدام الطريقة للحصول على المنشئين العامين للفئة التي ينتمي إليها الكائن.

  3. طُرق ال getMethods() يتم استخدام الطريقة للحصول على الأساليب العامة للفئة التي ينتمي إليها الكائن.

ال واجهة برمجة تطبيقات الانعكاس يستخدم بشكل رئيسي في:

IDE (بيئة التطوير المتكاملة) على سبيل المثال.كسوف، MyEclipse، NetBeans الخ.
أدوات التصحيح والاختبار وما إلى ذلك.

مزايا استخدام الانعكاس:

ميزات التوسعة: قد يستفيد التطبيق من الفئات الخارجية المعرفة من قبل المستخدم عن طريق إنشاء مثيلات كائنات قابلة للتوسعة باستخدام أسمائها المؤهلة بالكامل.

أدوات التصحيح والاختبار: يستخدم مصححو الأخطاء خاصية الانعكاس لفحص الأعضاء الخاصين في الفصول الدراسية.

العيوب:

النفقات العامة للأداء: تتميز العمليات العاكسة بأداء أبطأ من نظيراتها غير العاكسة، ويجب تجنبها في أقسام التعليمات البرمجية التي يتم استدعاؤها بشكل متكرر في التطبيقات الحساسة للأداء.

التعرض للداخلية: يكسر الكود الانعكاسي التجريدات وبالتالي قد يغير السلوك مع ترقيات النظام الأساسي.

المرجع: انعكاس جافا javarevisited.blogspot.in

الانعكاس عبارة عن مجموعة من الوظائف التي تسمح لك بالوصول إلى معلومات وقت التشغيل الخاصة ببرنامجك وتعديل سلوكه (مع بعض القيود).

إنه مفيد لأنه يسمح لك بتغيير سلوك وقت التشغيل اعتمادًا على المعلومات التعريفية لبرنامجك، أي أنه يمكنك التحقق من نوع الإرجاع للوظيفة وتغيير الطريقة التي تتعامل بها مع الموقف.

في C# على سبيل المثال، يمكنك تحميل تجميع (ملف .dll) في وقت التشغيل وفحصه والتنقل عبر الفئات واتخاذ الإجراءات وفقًا لما وجدته.كما يتيح لك أيضًا إنشاء مثيل لفئة في وقت التشغيل، واستدعاء طريقتها، وما إلى ذلك.

أين يمكن أن تكون مفيدة؟ليس مفيدًا في كل مرة ولكن في المواقف الملموسة.على سبيل المثال، يمكنك استخدامه للحصول على اسم الفئة لأغراض تسجيل الدخول، ولإنشاء معالجات للأحداث ديناميكيًا وفقًا لما هو محدد في ملف التكوين وما إلى ذلك...

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

public class Test {

    public void firstMoveChoice(){
        System.out.println("First Move");
    } 
    public void secondMOveChoice(){
        System.out.println("Second Move");
    }
    public void thirdMoveChoice(){
        System.out.println("Third Move");
    }

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
        Test test = new Test();
        Method[] method = test.getClass().getMethods();
        //firstMoveChoice
        method[0].invoke(test, null);
        //secondMoveChoice
        method[1].invoke(test, null);
        //thirdMoveChoice
        method[2].invoke(test, null);
    }

}

الانعكاس هو السماح للأشياء برؤية مظهرها.يبدو أن هذه الحجة لا علاقة لها بالتفكير.في الواقع، هذه هي القدرة على "تحديد الذات".

إن الانعكاس في حد ذاته هو كلمة تشير إلى اللغات التي تفتقر إلى القدرة على معرفة الذات والاستشعار الذاتي مثل Java وC#.نظرًا لأنهم لا يملكون القدرة على معرفة الذات، فعندما نريد أن نلاحظ كيف يبدو الأمر، يجب أن يكون لدينا شيء آخر للتفكير في كيف يبدو الأمر.يمكن للغات الديناميكية الممتازة مثل Ruby وPython إدراك الانعكاس الخاص بها دون مساعدة الأفراد الآخرين.يمكننا القول أن كائن Java لا يمكنه إدراك شكله بدون مرآة، وهو كائن من فئة الانعكاس، لكن الكائن في بايثون يمكنه إدراكه بدون مرآة.ولهذا السبب نحن بحاجة إلى التفكير في جافا.

أريد فقط أن أضيف نقطة إلى كل ما تم إدراجه.

مع واجهة برمجة تطبيقات الانعكاس يمكنك كتابة عالمية toString() طريقة لأي كائن.

ومن المفيد في التصحيح.

هنا بعض الأمثلة:

class ObjectAnalyzer {

   private ArrayList<Object> visited = new ArrayList<Object>();

   /**
    * Converts an object to a string representation that lists all fields.
    * @param obj an object
    * @return a string with the object's class name and all field names and
    * values
    */
   public String toString(Object obj) {
      if (obj == null) return "null";
      if (visited.contains(obj)) return "...";
      visited.add(obj);
      Class cl = obj.getClass();
      if (cl == String.class) return (String) obj;
      if (cl.isArray()) {
         String r = cl.getComponentType() + "[]{";
         for (int i = 0; i < Array.getLength(obj); i++) {
            if (i > 0) r += ",";
            Object val = Array.get(obj, i);
            if (cl.getComponentType().isPrimitive()) r += val;
            else r += toString(val);
         }
         return r + "}";
      }

      String r = cl.getName();
      // inspect the fields of this class and all superclasses
      do {
         r += "[";
         Field[] fields = cl.getDeclaredFields();
         AccessibleObject.setAccessible(fields, true);
         // get the names and values of all fields
         for (Field f : fields) {
            if (!Modifier.isStatic(f.getModifiers())) {
               if (!r.endsWith("[")) r += ",";
               r += f.getName() + "=";
               try {
                  Class t = f.getType();
                  Object val = f.get(obj);
                  if (t.isPrimitive()) r += val;
                  else r += toString(val);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }
         }
         r += "]";
         cl = cl.getSuperclass();
      } while (cl != null);

      return r;
   }    
}

من وثائق جافا صفحة

java.lang.reflect توفر الحزمة فئات وواجهات للحصول على معلومات عاكسة حول الفئات والكائنات.يسمح الانعكاس بالوصول البرمجي إلى المعلومات حول الحقول والأساليب ومنشئات الفئات المحملة، واستخدام الحقول والأساليب والمنشئات المنعكسة للعمل على نظيراتها الأساسية، ضمن القيود الأمنية.

AccessibleObject يسمح بقمع عمليات التحقق من الوصول إذا لزم الأمر ReflectPermission متاح.

الطبقات في هذه الحزمة، جنبا إلى جنب مع java.lang.Class استيعاب تطبيقات مثل مصححات الأخطاء والمترجمين الفوريين ومفتشي الكائنات ومتصفحات الفئات والخدمات مثل Object Serialization و JavaBeans التي تحتاج إلى الوصول إلى الأعضاء العامين للكائن المستهدف (استنادًا إلى فئة وقت التشغيل الخاصة به) أو الأعضاء المعلنين بواسطة فئة معينة

ويشمل الوظائف التالية.

  1. الحصول على كائنات الفئة،
  2. فحص خصائص الطبقة (الحقول، الأساليب، المنشئات)،
  3. تحديد والحصول على قيم الحقول،
  4. أساليب الاستدعاء
  5. إنشاء مثيلات جديدة للكائنات.

الق نظرة على هذا توثيق رابط للطرق التي كشفها Class فصل.

من هذا شرط (بقلم دينيس سوسنوسكي، رئيس شركة Sosnoski Software Solutions, Inc) وهذا شرط (الاستكشافات الأمنية pdf):

أستطيع أن أرى عيوبًا كبيرة من استخدامات استخدام الانعكاس

مستخدم الانعكاس:

  1. فهو يوفر طريقة متعددة الاستخدامات لربط مكونات البرنامج ديناميكيًا
  2. إنه مفيد لإنشاء مكتبات تعمل مع الكائنات بطرق عامة جدًا

عيوب الانعكاس:

  1. يكون الانعكاس أبطأ بكثير من التعليمات البرمجية المباشرة عند استخدامه للوصول إلى الحقل والطريقة.
  2. يمكن أن يحجب ما يحدث بالفعل داخل التعليمات البرمجية الخاصة بك
  3. تجاوز التعليمات البرمجية المصدر يمكن أن يخلق مشاكل في الصيانة
  4. يعد رمز الانعكاس أيضًا أكثر تعقيدًا من الكود المباشر المقابل
  5. يسمح بانتهاك قيود أمان Java الرئيسية مثل حماية الوصول إلى البيانات ونوع السلامة

الانتهاكات العامة:

  1. تحميل الطبقات المقيدة،
  2. الحصول على مراجع للمنشئين أو الأساليب أو المجالات ذات الفئة المقيدة،
  3. إنشاء مثيلات كائن جديدة، أو استدعاء الأساليب، أو الحصول على أو تعيين قيم الحقول لفئة مقيدة.

ألقِ نظرة على سؤال SE المتعلق بإساءة استخدام ميزة الانعكاس:

كيف أقرأ مجالًا خاصًا في Java؟

ملخص:

يمكن أيضًا أن يؤدي الاستخدام غير الآمن لوظائفه من خلال رمز النظام إلى اختراق وضع أمان Javaل. لذا استخدم هذه الميزة باعتدال

كما يوحي الاسم نفسه، فإنه يعكس ما يحمله على سبيل المثال طريقة الفئة، وما إلى ذلك بصرف النظر عن توفير ميزة لاستدعاء طريقة إنشاء المثيل ديناميكيًا في وقت التشغيل.

يتم استخدامه من قبل العديد من الأطر والتطبيقات تحت الخشب لاستدعاء الخدمات دون معرفة الكود فعليًا.

Reflection لديه الكثير الاستخدامات.الشيء الذي أعرفه أكثر هو أن أتمكن من إنشاء التعليمات البرمجية بسرعة.

أي:الفئات الديناميكية ، والوظائف ، والمُنشئين - بناءً على أي بيانات (نتائج XML/Array/SQL/Hardcoded/Etc ..)

يمنحك الانعكاس القدرة على كتابة تعليمات برمجية أكثر عمومية.يسمح لك بإنشاء كائن في وقت التشغيل واستدعاء طريقته في وقت التشغيل.ومن ثم يمكن جعل البرنامج ذو معلمات عالية.كما يسمح أيضًا باستبطان الكائن والفئة لاكتشاف متغيراته وطريقة تعرضه للعالم الخارجي.

أريد الإجابة على هذا السؤال بمثال.أولاً Hibernate استخدامات المشروع Reflection API لتوليد CRUD عبارات لسد الفجوة بين التطبيق قيد التشغيل ومخزن الثبات.عندما تتغير الأمور في المجال، فإن Hibernate يجب أن يعرفها لنقلها إلى مخزن البيانات والعكس صحيح.

يعمل بدلا من ذلك Lombok Project.فهو يقوم فقط بإدخال التعليمات البرمجية في وقت الترجمة، مما يؤدي إلى إدراج التعليمات البرمجية في فئات المجال الخاص بك.(أعتقد أنه لا بأس بالنسبة للحروف والمستوطنين)

Hibernate اختار reflection لأنه له تأثير ضئيل على عملية إنشاء التطبيق.

ومن جافا 7 لدينا MethodHandles, ، والذي يعمل ك Reflection API.في المشاريع، للعمل مع أدوات قطع الأشجار، نقوم فقط بنسخ ولصق الكود التالي:

Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

لأنه من الصعب ارتكاب خطأ مطبعي في هذه الحالة.

كما أجد أنه من الأفضل أن أشرح بالقدوة ولا يبدو أن أيًا من الإجابات تفعل ذلك ...

من الأمثلة العملية على استخدام الانعكاسات خادم لغة Java المكتوب بلغة Java أو خادم لغة PHP المكتوب بلغة PHP، وما إلى ذلك.يوفر خادم اللغة قدرات IDE الخاصة بك مثل الإكمال التلقائي والانتقال إلى التعريف ومساعدة السياق وأنواع التلميحات والمزيد.لكي تكون جميع أسماء العلامات (الكلمات التي يمكن إكمالها تلقائيًا) متطابقة عند الضغط، دعنا نقول، فاتورة غير مدفوعة وإظهار جميع التلميحات، يجب على خادم اللغة فحص كل شيء يتعلق بالفصل، بما في ذلك كتل المستندات والأعضاء الخاصين.لذلك يحتاج إلى انعكاس للفئة المذكورة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top