لا تزال هذه المقالة تستخدم أمثلة صغيرة لتوضيحها ، لأنني أشعر دائمًا أن القائمة على الحالات هي الأفضل ، وإلا إذا قرأت النظرية فقط ، فلن تفهمها بعد قراءتها. ومع ذلك ، يوصى بأن تنظر إلى الوراء إلى النظرية بعد قراءة المقال ولديك فهم أفضل.
النص الرئيسي يبدأ أدناه.
[الحالة 1] الحصول على الحزمة الكاملة واسم الفئة من خلال كائن
الحزمة تعكس ؛ /*** احصل على اسم الحزمة الكامل واسم الفئة من خلال كائن**/class demo {// رموز أخرى ...} class hello {public static void main (string [] args) {demo demo = new demo () ؛ system.out.println (demo.getClass (). getName ()) ؛ }}【النتيجة الجري】: resperence.demo
إضافة جملة: جميع كائنات الفئات هي في الواقع مثيلات من الفصل.
【الحالة 2】 كائن فئة مثبتة
الحزمة تعكس ؛ Class Demo {// أخرى رموز ...} class hello {public static void main (string [] args) {class <؟> demo1 = null ؛ فئة <؟> demo2 = null ؛ فئة <؟> demo3 = null ؛ حاول {// عمومًا محاولة استخدام هذا النموذج demo1 = class.forname ("reflect.demo") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } demo2 = new demo (). getClass () ؛ demo3 = demo.class ؛ System.out.println ("اسم الفئة"+demo1.getName ()) ؛ system.out.println ("اسم الفئة"+demo2.getName ()) ؛ system.out.println ("اسم الفئة"+demo3.getName ()) ؛ }} نتائج التشغيل】:
فئة namereflect.demo
فئة namereflect.demo
فئة namereflect.demo
[الحالة 3] كائنات مثالية لفئات أخرى من خلال الفصل
الكائنات التي تم تأسيسها عن طريق بناء غير المعلمات
الشخص العام (اسم السلسلة ، int age) {this.age = age ؛ this.name = name ؛ }ثم استمر في تشغيل البرنامج أعلاه ، وسيظهر:
لذلك عندما تكتب كائنات تستخدم فئة لإنشاء فئات أخرى ، يجب عليك تحديد مُنشئك بدون معلمات.
[CASE] مُنشئو المكالمات في فئات أخرى من خلال الفصل (يمكنك أيضًا إنشاء كائنات من الفئات الأخرى من خلال الفصل بهذه الطريقة)
الحزمة تعكس ؛ استيراد java.lang.reflect.constructor ؛ الفئة شخص {public person () {} public person (اسم السلسلة) {this.name = name ؛ } الشخص العام (int age) {this.age = Age ؛ } الشخص العام (اسم السلسلة ، int age) {this.age = age ؛ this.name = name ؛ } السلسلة العامة getName () {return name ؛ } public int getage () {return Age ؛ } Override public string toString () {return "["+this.name+""+this.age+"]" ؛ } اسم السلسلة الخاصة ؛ عصر INT الخاص ؛ } class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } شخص per1 = null ؛ شخص per2 = فارغ ؛ شخص per3 = فارغ ؛ شخص per4 = فارغة ؛ // احصل على جميع مُنشئات المنشئات <؟> cons [] = demo.getConstructors () ؛ حاول {per1 = (شخص) سلبيات [0] .NewInstance () ؛ per2 = (شخص) سلبيات [1]. newinstance ("Rollen") ؛ per3 = (شخص) سلبيات [2]. newinstance (20) ؛ per4 = (شخص) سلبيات [3]. newinstance ("Rollen" ، 20) ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } system.out.println (per1) ؛ system.out.println (per2) ؛ system.out.println (per3) ؛ system.out.println (per4) ؛ }}نتائج التشغيل】:
[NULL 0]
[رولن 0]
[NULL 20]
[رولين 20]
【قضية】
إرجاع الواجهة التي تنفذها الفصل:
الحزمة تعكس ؛ Interface China {public Static Final String Name = "Rollen" ؛ العمر الثابت العام = 20 ؛ الفراغ العام sayschina () ؛ الفراغ العام يقول هيلو (اسم السلسلة ، int age) ؛ } شخص ما ينفذ الصين {public person () {} الشخص العام (سلسلة الجنس) {this.sex = sex ؛ } سلسلة عامة getSex () {return sex ؛ } public void setSex (سلسلة الجنس) {this.sex = sex ؛ } Override public void saychina () {system.out.println ("Hello ، China") ؛ } override public void sealhello (اسم السلسلة ، int age) {system.out.println (name+""+age) ؛ } سلسلة جنسية خاصة ؛ } class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } // حفظ جميع واجهات فئة <؟> intes [] = demo.getInterfaces () ؛ لـ (int i = 0 ؛ i <intes.length ؛ i ++) {system.out.println ("الواجهة المنفذة"+intes [i] .getName ()) ؛ }}}نتائج التشغيل】:
الواجهة المنفذة تعكس
(لاحظ أن الأمثلة التالية ستستخدم فئة الشخص في هذا المثال ، لذلك من أجل توفير المساحة ، لن نلصق جزء رمز الشخص هنا ، فقط رمز الفئة الرئيسية Hello)
【الحالة】: احصل على فئة الأصل في فصول أخرى
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } // الحصول على فئة الفئة الأصل <؟> temp = demo.getSuperClass () ؛ System.out.println ("فئة الوالدين الموروثة هي:"+temp.getName ()) ؛ }}【نتائج التشغيل】
فئة الوالد الموروثة هي: java.lang.object
【الحالة】: الحصول على جميع المنشئين في فصول أخرى
يتطلب هذا المثال إضافة استيراد java.lang.reflect.* في بداية البرنامج ؛
ثم اكتب الفصل الرئيسي على النحو التالي:
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } مُنشئ <؟> cons [] = demo.getConstructors () ؛ لـ (int i = 0 ؛ i <cons.length ؛ i ++) {system.out.println ("constructor:"+cons [i]) ؛ }}}نتائج التشغيل】:
طريقة الإنشاء: انعكاس عام. person ()
مُنشئ: Public Refferen
لكن القراء الحذرين سيجدون أن المُنشئ أعلاه لا يحتوي على معدلات مثل العامة أو الخاصة
دعنا نحصل على المعدل في المثال التالي
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } مُنشئ <؟> cons [] = demo.getConstructors () ؛ لـ (int i = 0 ؛ i <cons.length ؛ i ++) {class <؟> p [] = cons [i] .getParameterTypes () ؛ System.out.print ("Constructor:") ؛ int mo = cons [i] .getModifiers () ؛ system.out.print (modifier.toString (mo)+"") ؛ system.out.print (cons [i] .getName ()) ؛ System.out.print ("(" (") ؛ for (int j = 0 ؛ j <p.length ؛ ++ j) {system.out.print (p [j] .getName ()+" arg "+i) ؛ if (j <p.llength-1) {system.out.print (" ، ") ؛}}}}} }}}نتائج التشغيل】:
مُنشئ: عام انعكاس. person () {}
مُنشئ: public reflect.person (java.lang.string arg1) {}
في بعض الأحيان قد تكون هناك استثناءات في طريقة ، هاها. لنلقي نظرة:
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } طريقة طريقة [] = demo.getMethods () ؛ لـ (int i = 0 ؛ i <method.length ؛ ++ i) {class <؟> returntype = method [i] .getReturnType () ؛ الفئة <؟> para [] = method [i] .getParameterTypes () ؛ int temp = method [i] .getModifiers () ؛ system.out.print (modifier.toString (temp)+"") ؛ system.out.print (returntype.getName ()+"") ؛ system.out.print (method [i] .getName ()+"") ؛ System.out.print ("(" (") ؛ for (int j = 0 ؛ j <para.length ؛ ++ j) {system.out.print (para [j] .getName ()+" "+" arg "+j) ؛ if (j <para.length-1) {system.out.print (" ، "،") ؛}}}} if (exce.length> 0) {system.out.print (") رميات") ؛ لـ (int k = 0 ؛ k <exce.length ؛ ++ k) {system.out.print (exce [k] .getName ()+"") ؛ if (k <exce.length-1) {system.out.print ("،") ؛ }}}} آخر {system.out.print (")") ؛ } system.out.println () ؛ }}} نتائج التشغيل】:[الحالة] بعد ذلك ، دعنا نحصل على جميع خصائص الفصول الأخرى. أخيرًا ، سأقوم بفرزهم معًا ، أي للحصول على إطار عمل كامل من خلال الفصل
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } System.out.println ("====================================================================================================================== ============================================================================================================================================================================= ============================================================================================================================================================================= =================================================================================================================================================================== MODIFIER int mo = field [i]. System.out.println ("================================================================================== =========================================================================================================================================== ==================================================================================================================================== =========================================================================================================================================== fileD1 = demo.getfields () ؛ لـ (int j = 0 ؛ j <filed1.length ؛ j ++) {// modifier int mo = filed1 [j] .getModifiers () ؛ سلسلة priv = modifier.toString (mo) ؛ // property type class <؟> type = filed1 [j] .getType () ؛ System.out.println (priv + "" + type.getName () + "" + filed1 [j] .getName () + "؛") ؛ }}}نتائج التشغيل】:
==================================================
الخاص java.lang.string الجنس ؛
========================================================
java.lang.string الاسم النهائي الثابت ؛
عصر int الثابت العام ؛
[الحالة] في الواقع ، يمكن أيضًا استدعاء الطرق في فئات أخرى من خلال التفكير:
class hello {public static void main (string [] args) {class <؟> demo = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } حاول {// استدعاء طريقة saychina في طريقة فئة الشخص = demo.getMethod ("Saychina") ؛ method.invoke (demo.newinstance ()) ؛ // استدعاء طريقة sayhello للشخص = demo.getMethod ("sayhello" ، string.class ، int.class) ؛ method.invoke (Demo.newinstance () ، "Rollen" ، 20) ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }}}نتائج التشغيل】:
مرحبا الصين
رولن 20
【الحالة】 مجموعة المكالمات والحصول على طرق للفئات الأخرى
class hello {public static void main (string [] args) {class <؟> demo = null ؛ كائن obj = null ؛ حاول {demo = class.forname ("reflect.person") ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } حاول {obj = demo.newinstance () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } setter (obj ، "sex" ، "male" ، string.class) ؛ getter (OBJ ، "الجنس") ؛ } / ** * param obj * كائن العملية * param att * سمات العملية * * / public static void getter (Object obj ، string att) {try {method method = obj.getclass (). getMethod ("get" + att) ؛ System.out.println (method.invoke (obj)) ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }} / ** * param obj * كائن العملية * param att * سمات العملية * @param value * set value * param type * سمات المعلمة * * / public static void setter (Object obj ، string att ، combor compl ، class <؟ method.invoke (OBJ ، القيمة) ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }}} // end classنتائج التشغيل】:
ذكر
【الحالة】 التشغيل عن طريق التفكير
class hello {public static void main (string [] args) يلقي الاستثناء {class <؟> demo = null ؛ كائن obj = null ؛ demo = class.forname ("refles.person") ؛ obj = demo.newinstance () ؛ حقل الحقل = demo.getDeclaredField ("الجنس") ؛ Field.SetAccessible (صحيح) ؛ field.set (obj ، "male") ؛ System.out.println (field.get (obj)) ؛ }} // end class[CASE] الحصول على معلومات الصفيف وتعديلها من خلال التفكير:
استيراد java.lang.reflect.*؛ class hello {public static void main (string [] args) {int [] temp = {1،2،3،4،5} ؛ class <؟> demo = temp.getClass (). getComponentType () ؛ System.out.println ("نوع المصفوفة:"+demo.getName ()) ؛ System.out.println ("طول الصفيف"+Array.getLength (temp)) ؛ System.out.println ("العنصر الأول من المصفوفة:"+Array.get (temp ، 0)) ؛ Array.set (temp ، 0 ، 100) ؛ System.out.println ("بعد تعديل العنصر الأول من المصفوفة هو:"+array.get (temp ، 0)) ؛ }}نتائج التشغيل】:
نوع الصفيف: int
طول الصفيف 5
العنصر الأول من المصفوفة: 1
بعد التعديل ، العنصر الأول من المصفوفة هو: 100
【الحالة】 تعديل حجم الصفيف من خلال الانعكاس
class hello {public static void main (string [] args) {int [] temp = {1،2،3،4،5،6،7،8،9} ؛ int [] newtemp = (int []) arrayinc (temp ، 15) ؛ طباعة (Newtemp) ؛ System.out.println ("=============================================================================== ========================================================================================================================== string []) Arrayinc (ATR ، 8) ؛ System.ArrayCopy (OBJ ، Newarr ، 0 ، CO) ؛ Array.GetLength (OBJ) ؛نتائج التشغيل】:
طول الصفيف هو: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 ==================================================
طول الصفيف هو: 8
ABC NULL NULL NULL NULL
عامل ديناميكي
[الحالة] أولاً ، دعنا نلقي نظرة على كيفية الحصول على محمل الفصل:
اختبار الفئة {} class hello {public static void main (string [] args) {test t = new test () ؛ System.out.println ("classloader"+t.getClass (). getClassLoader (). getClass (). getName ()) ؛ }}【إخراج البرنامج】:
class loader sun.misc.launcher $ appclassloader
في الواقع ، هناك ثلاثة أنواع من اللوادر الطبقية في جافا.
1) Bootstrap classloader يتم كتابة هذا المحمل في C ++ ونادراً ما ينظر إليه في التطور العام.
2) يتم استخدام extension classloader لتحميل الفئات الموسعة ، والتي تتوافق بشكل عام مع الفئات في دليل JRE/LIB/EXT
3) يقوم AppClassloader بتحميل الفئة المحددة بواسطة ClassPath وهي المحمل الأكثر استخدامًا. وهو أيضًا اللودر الافتراضي في جافا.
إذا كنت ترغب في إكمال وكيل ديناميكي ، فأنت بحاجة أولاً إلى تحديد فئة فرعية لواجهة InvocationHandler ، وتم الانتهاء من التشغيل المحدد للوكيل.
الحزمة تعكس ؛ استيراد java.lang.reflect.*؛ // تحديد واجهة واجهة المشروع {STRING SENER (اسم السلسلة ، int age) ؛ }. }} class myinvocationHandler تنفذ invocationHandler {private object obj = null ؛ الكائن العام bind (object obj) {this.Obj = obj ؛ return proxy.newproxyinstance (obj.getClass (). getClassloader () ، obj .getClass (). } Override الكائن العام استدعاء (وكيل الكائن ، طريقة الطريقة ، الكائن [] args) يلقي رمي {كائن temp = method.invoke (this.obj ، args) ؛ عودة درجة الحرارة. }} class hello {public static void main (string [] args) {myinvocationHandler demo = new myinvocationHandler () ؛ الموضوع الفرعي = (الموضوع) demo.bind (new realSubject ()) ؛ معلومات السلسلة = sub.say ("Rollen" ، 20) ؛ System.out.println (info) ؛ }} نتائج التشغيل】:
رولن 20
دورة حياة الفصل
بعد تجميع الفصل ، فإن الخطوة التالية هي البدء في استخدام الفصل. إذا كنت ترغب في استخدام فصل ، فمن المؤكد أنه لا ينفصل عن JVM. أثناء تنفيذ البرنامج ، يتم الانتهاء من JVM من خلال هذه الخطوات الثلاث: التحميل والربط والتهيئة.
يتم تحميل الفصل من خلال تحميل فئة. يقوم المحمل بتحميل الملف الثنائي لملف .class في منطقة طريقة JVM ويقوم بإنشاء كائن java.lang.class الذي يصف هذه الفئة في منطقة الكومة. تستخدم لتغليف البيانات. ولكن لن يتم تحميل نفس الفئة إلا بواسطة محمل الفئة من قبل
الروابط لتجميع البيانات الثنائية في حالة يمكن تشغيلها.
ينقسم الرابط إلى ثلاث مراحل: التحقق والتحضير والتحليل
يتم استخدام التحقق بشكل عام لتأكيد ما إذا كان هذا الملف الثنائي مناسبًا لـ JVM الحالي (الإصدار).
التحضير هو تخصيص مساحة الذاكرة للأعضاء الثابتة. وضبط القيم الافتراضية
يشير التحليل إلى عملية تحويل الكود في المجموعة الثابتة كمرجع مباشر حتى يمكن استخدام جميع المراجع الرمزية من قبل برنامج التشغيل (إنشاء مراسلات كاملة)
بعد الانتهاء ، تتم تهيئة النوع. بعد التهيئة ، يمكن استخدام كائن الفئة بشكل طبيعي. بعد عدم استخدام كائن ، سيتم جمع القمامة. مساحة مجانية.
عندما لا يشير أي مرجع إلى كائن الفصل ، سيتم إلغاء تثبيته ، مع إنهاء دورة حياة الفصل
استخدام انعكاس لوضع المصنع
دعنا نلقي نظرة على وضع المصنع إذا كنت لا تحتاج إلى انعكاس:
/ *** Author Rollen-Holt Factory Mode of Design Pattern*/ Interface Fruit {public Abstract void eat () ؛ } Class Apple تنفذ Fruit {public void eat () {system.out.println ("Apple") ؛ }} Class Orange تنفذ الفاكهة {public void eat () {system.out.println ("Orange") ؛ }} // بناء فئة المصنع // بمعنى آخر ، إذا كنا بحاجة فقط إلى تعديل فئة المصنع عند إضافة مثيلات أخرى في مصنع الفئة المستقبلية {public static fruit getInstance (String fruitName) {fruit f = null ؛ if ("Apple" .equals (fruitName)) {f = new Apple () ؛ } if ("Orange" .equals (fruitName)) {f = new Orange () ؛ } إرجاع f ؛ }} class hello {public static void main (string [] a) {fruit f = factory.getInstance ("Orange") ؛ f.eat () ؛ }} وبهذه الطريقة ، عندما نضيف فئة فرعية ، نحتاج إلى تعديل فئة المصنع. إذا أضفنا الكثير من الفئات الفرعية ، فسوف نتغير كثيرًا.
الآن دعونا نلقي نظرة على آلية الانعكاس باستخدام:
الحزمة تعكس ؛ واجهة الفاكهة {Public Abstract void eat () ؛ } Class Apple تنفذ Fruit {public void eat () {system.out.println ("Apple") ؛ }} Class Orange تنفذ الفاكهة {public void eat () {system.out.println ("Orange") ؛ }} class factory {public static fruit getInstance (string className) {fruit f = null ؛ حاول {f = (fruit) class.forname (className) .NewInstance () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } إرجاع f ؛ }} class hello {public static void main (string [] a) {fruit f = factory.getInstance ("resperence.apple") ؛ if (f! = null) {f.eat () ؛ }}} الآن حتى لو أضفنا أكبر عدد ممكن من الفئات الفرعية ، لا يلزم تعديل فئة المصنع.
على الرغم من أن الحب أعلاه يمكن أن يحصل على مثيل الواجهة من خلال الانعكاس ، إلا أنه يحتاج إلى تمرير في الحزمة الكاملة واسم الفصل. علاوة على ذلك ، لا يمكن للمستخدمين معرفة عدد الفئات الفرعية التي يمكن استخدامها في واجهة ، لذلك نقوم بتكوين الفئات الفرعية المطلوبة في شكل ملفات السمات.
لنلقي نظرة على: وضع المصنع يجمع بين ملفات السمات
أولا قم بإنشاء ملف Fruit.Properties.
المحتويات:
Apple = reflect.apple Orange = respense.orange
ثم اكتب رمز الفصل الرئيسي:
الحزمة تعكس ؛ استيراد java.io.*؛ استيراد java.util.*؛ واجهة الفاكهة {Public Abstract void eat () ؛ } Class Apple تنفذ Fruit {public void eat () {system.out.println ("Apple") ؛ }} Class Orange تنفذ الفاكهة {public void eat () {system.out.println ("Orange") ؛ }} // تشغيل فئة ملف الخصائص init {public static properties getPro () يلقي fileNotfoundException ، ioException {properties pro = new properties () ؛ ملف f = ملف جديد ("fruit.properties") ؛ if (f.exists ()) {pro.load (new FileInputStream (f)) ؛ } else {pro.setProperty ("Apple" ، "reflect.apple") ؛ pro.setProperty ("Orange" ، "reflect.orange") ؛ Pro.store (FileOutputStream (F) ، "فئة الفاكهة") ؛ } return pro ؛ }} class factory {public static fruit getInstance (string className) {fruit f = null ؛ حاول {f = (fruit) class.forname (className) .NewInstance () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } إرجاع f ؛ }} class hello {public static void main (string [] a) trows fileNotfoundException ، ioException {properties pro = init.getPro () ؛ الفاكهة f = factory.getInstance (pro.getProperty ("Apple")) ؛ if (f! = null) {f.eat () ؛ }}} 【Run Running】: Appleالتحليل المذكور أعلاه لانعكاس Java (الموصى به) هو كل المحتوى الذي أشاركه معك. آمل أن تتمكن من إعطائك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.