1. نقاط المعرفة حول السيطرة على الكائن والذاكرة
1. عملية التهيئة لمتغيرات JAVA ، بما في ذلك المتغيرات المحلية ، متغيرات الأعضاء (متغيرات المثيل ومتغيرات الفئة).
2. في علاقة الميراث ، عندما يختلف نوع وقت الترجمة ونوع وقت التشغيل عن نوع وقت الترجمة لمتغير مرجع الكائن المستخدم ، هناك اختلاف في خصائص وطرق الوصول إلى الكائن.
3. خصائص المعدل النهائي.
2. تقسيم وعملية تهيئة متغيرات Java
يمكن تقسيم متغيرات برامج Java تقريبًا إلى متغيرات الأعضاء والمتغيرات المحلية. يمكن تقسيم متغيرات الأعضاء إلى متغيرات مثيل (المتغيرات غير الستاصلة) ومتغيرات الفئة (المتغيرات الثابتة). بشكل عام ، ستظهر المتغيرات المحلية التي نواجهها في المواقف التالية:
(1) المعلمة الرسمية: يتم تعيين المتغيرات المحلية المحددة في توقيع الطريقة بواسطة المتصل وتختفي مع انتهاء الطريقة.
(2) المتغيرات المحلية ضمن الطريقة: يجب تهيئة المتغيرات المحلية المحددة في الطريقة (تعيين قيمة أولية) في الطريقة ، وتختفي عندما يبدأ التهيئة المتغيرة وتنتهي.
(3) المتغيرات المحلية في كتلة الكود: يجب تهيئة المتغيرات المحلية المحددة في كتلة الكود (تعيين القيم الأولية) التي يجب عرضها في كتل التعليمات البرمجية. سوف يصدر ساري المفعول مع اكتمال التهيئة وتموت مع انتهاء كتلة الكود.
حزمة com.zlc.array ؛ الفئة العامة Testfield {{String B ؛ // إذا لم يتم تهيئته ، فسيقوم المترجم بالإبلاغ عن أن المتغير المحلي B قد لا يكون قد تم تهيئة System.out.println (B) ؛ } public static void main (string [] args) {int a ؛ // إذا لم يتم تهيئته ، فسيقوم المترجم بالإبلاغ عن أن المتغير المحلي A قد لا يتم تهيئة System.out.println (A) ؛ }} متغيرات الأعضاء المعدلة مع ثابت هي متغيرات فئة ، والتي تنتمي إلى الفصل نفسه. متغيرات الأعضاء التي لم يتم تعديلها مع ثابت هي متغيرات مثيل. الحالات التي تنتمي إلى هذا الفئة ، في نفس JVM ، يمكن لكل فئة أن تتوافق فقط مع كائن فئة واحد ، ولكن يمكن لكل فئة إنشاء كائنات Java متعددة. (أي أن متغير الفئة لا يتطلب سوى مساحة واحدة من الذاكرة ، وفي كل مرة ينشئ الفئة مثيلًا ، يحتاج إلى تخصيص مساحة لمتغير المثيل)
عملية التهيئة لمتغيرات المثيل: من منظور بناء الجملة ، يمكن للبرنامج تنفيذ تهيئة متغيرات المثيل في ثلاثة أماكن:
(1) حدد القيمة الأولية عند تحديد متغير مثيل.
(2) حدد القيمة الأولية لمتغيرات مثال في الكتل غير المنتظمة.
(3) حدد القيمة الأولية لمتغيرات مثال في المنشئ.
من بينها ، يتم تحديد وقت التهيئة للطريقتين (1) و (2) قبل (3) في المُنشئ ، ويتم تحديد أوامر التهيئة (1) و (2) بالترتيب الذي يتم ترتيبهما في رمز المصدر.
حزمة com.zlc.array ؛ الفئة العامة testfield {public testfield (int age) {system.out.println ("تهيئة this.age في المُنشئ ="+this.age) ؛ this.age = العمر ؛ } {system.out.println ("initialize in nonstatic blocks") ؛ العمر = 22 ؛ } // تهيئة العمر int = 15 ؛ الفراغ الثابت العام (سلسلة [] args) {testfield field = new testfield (24) ؛ system.out.println ("Final Age ="+field.age) ؛ }} نتيجة التشغيل هي: تهيئة هذا.
العمر الأخير = 24
إذا كنت تعرف كيفية استخدام Javap ، فيمكنك استخدام Javap -C XXXX (ملف الفئة) لمعرفة كيفية تجميع فئة Java.
عند تحديد متغير مثيل ، حدد القيمة الأولية. في كتلة التهيئة ، تكون حالة العبارة التي تحدد القيمة الأولية لمتغير المثيل متساويًا. بعد تجميع المترجم ومعالجته ، يتم ذكرها جميعًا في المنشئ. سيتم تقسيم عمر int المذكور أعلاه = 15 إلى الخطوتين التاليتين للتنفيذ:
1) عمري. عند إنشاء كائن Java ، يخصص النظام الذاكرة للكائن وفقًا للبيان.
2) العمر = 15 ؛ سيتم استخراج هذا البيان في مُنشئ فئة Java ويتم تنفيذه.
عملية التهيئة لمتغيرات الفئة: من منظور بناء الجملة ، يمكن للبرنامج تهيئة وتعيين القيم لمتغيرات الفئة من مكانين.
(1) حدد القيمة الأولية عند تحديد متغير الفئة.
(2) حدد القيمة الأولية لمتغيرات الفئة في كتلة ثابتة.
أمران التنفيذ هما نفس ترتيبهما في رمز المصدر. دعونا نعطي مثالًا صغيرًا غير طبيعي:
حزمة com.zlc.array ؛ الفئة testStatic {// Class Member Demo TestStatic مثيل Final Static TestStatic Demo = New TestStatic (15) ؛ // عضو الفئة ثابتة int age = 20 ؛ // مثيل المتغير curage int curage ؛ TestStatic العام (int years) {// todo todo tuto crage curage = age - years ؛ }} اختبار الفئة العامة {public static void main (string [] args) {system.out.println (testStatic.demo.curage) ؛ testStatic StaticDemo = اختبار جديد (15) ؛ System.out.println (StaticDemo.curage) ؛ }} تتم طباعة نتيجة الإخراج في سطرين. أحدهما هو طباعة متغير المثيل لتوضيح سمة الفئة TestStatic ، والثاني هو إخراج سمة المثيل لـ TestStatic من خلال staticdemo لكائن Java. وفقًا لعملية التهيئة لمتغير المثيل ومتغيرات الفئة التي قمنا بتحليلها أعلاه ، يمكننا استنتاجها:
1) في المرحلة الأولى من التهيئة ، عند تحميل الفئة ، تخصيص مساحة الذاكرة لمتغيرات الفئة العروض العاطفية والعمر. في هذا الوقت ، تكون القيم الافتراضية للعروض التجريبية والعمر فارغة و 0 على التوالي.
2) في المرحلة الثانية من التهيئة ، يقوم البرنامج بتعيين القيم الأولية للتجريبية والعمر بالتسلسل. يحتاج TestStatic (15) إلى استدعاء مُنشئ TestStatic. في هذا الوقت ، العمر = 0 ، وبالتالي فإن نتيجة الطباعة هي -15. عند تهيئة StaticDemo ، تم تعيين العمر إلى 20 ، وبالتالي فإن نتيجة الإخراج هي 5.
3. الفرق بين متغيرات الأعضاء الموروثة وأساليب الأعضاء الموروثة في علاقات الميراث
عند إنشاء أي كائن Java ، سيقوم البرنامج دائمًا باستدعاء كتلة الفئة غير المنطقية ومُنشئ الفئة الأصل للفئة الأصل أولاً ، وأخيراً استدعاء الكتلة غير المستقلة ومُنشئ هذه الفئة. يتم تقسيم استدعاء مُنشئ الفئة الأم من خلال مُنشئ الفئة الفرعية بشكل عام إلى حالتين: أحدهما مكالمة ضمنية ، والآخر هو عرض فائق للاتصال بمنشئ الفئة الأصل.
يمكن لطريقة فئة الطفل استدعاء متغير المثيل للفئة الأصل. وذلك لأن فئة الطفل ترث فئة الأصل وستحصل على متغيرات الأعضاء وطرق فئة الأصل. ومع ذلك ، لا يمكن أن تصل طريقة الفئة الأصل إلى متغير المثيل لفئة الطفل لأن فئة الأصل لا تعرف الفئة التي سترثها ونوع متغيرات الأعضاء التي ستضيفها فئة الفرعية. بالطبع ، في بعض الأمثلة المتطرفة ، لا يزال بإمكان فئة الأصل استدعاء متغير فئة الطفل. على سبيل المثال: تقوم فئة الطفل بإعادة كتابة طريقة الفئة الأصل وتطبع القيمة الافتراضية بشكل عام ، لأنه لم يتم تهيئة متغير المثيل لفئة الطفل في هذا الوقت.
حزمة com.zlc.array ؛ فئة الأب {int age = 50 ؛ الأب العام () {// todo todo tuto constructor stub System.out.println (this.getClass ()) ؛ //this.sonmethod () ؛ لا يمكن استدعاء المعلومات () ؛ } public void info () {system.out.println (Age) ؛ }} يمتد ابن الفئة العامة الأب {int age = 24 ؛ الابن العام (int Age) {// todo constructor constructor this.age = Age ؛ } Override public void info () {// todo method method method system.err.println (Age) ؛ } public static void main (string [] args) {new son (28) ؛ }. }} وفقًا لاستنتاجنا الطبيعي ، يتم استدعاء مُنشئ الفئة الأصل ضمنيًا من خلال الفئة الفرعية ، ويتم استدعاء طريقة المعلومات () في مُنشئ الفئة الأصل (ملاحظة: لم أقل أن الفئة الأصل تسمى). من الناحية النظرية ، فإنه يخرج متغير مثيل العمر للفئة الأصل. من المتوقع أن تكون نتيجة الطباعة 50 ، ولكن نتيجة الإخراج الفعلية هي 0. تحليل السبب:
1) لم يكتمل تخصيص الذاكرة لكائنات Java في المنشئ. يقوم المُنشئ فقط بإكمال عملية تخصيص التهيئة. وهذا هو ، قبل استدعاء مُنشئ الفئة الأصل ، قام JVM بتصنيف مساحة الذاكرة لكائن SON. تخزن هذه الفضاء سمتين عامين ، إحداها هي عصر الفئة الفرعية والآخر هو عصر الفئة الأم.
2) عند الاتصال بالابن الجديد (28) ، يمثل هذا الكائن كائنًا كائنًا فئة فرعية. يمكننا طباعة الكائن. ومع ذلك ، يتم تنفيذ عملية التهيئة الحالية في مُنشئ فئة الأصل ، ولا يمكن استدعاؤها من خلال this.sonmethod () ، لأن نوع الترجمة هذا هو الأب.
3) عندما يختلف نوع وقت الترجمة للمتغير عن نوع وقت التشغيل ، عند الوصول إلى متغير المثيل لكائن المرجع الخاص به من خلال المتغير ، يتم تحديد قيمة متغير المثيل بنوع المتغير المعلن. ومع ذلك ، عندما تشير طريقة مثيل الكائن من خلال المتغير ، يتم تحديد سلوك الطريقة بواسطة الكائن الذي يشير إليه بالفعل. لذلك ، تسمى طريقة المعلومات الخاصة بالفئة الفرعية هنا ، وبالتالي يتم طباعة عصر الفئة الفرعية. نظرًا لأن العمر لم يتم تهيئته بشكل عاجل ، فإن القيمة الافتراضية هي 0.
بعبارات Layman ، عندما يكون النوع المعلن غير متوافق مع النوع الجديد الحقيقي ، فإن السمة المستخدمة هي الفئة الأصل والطريقة التي تسمى فئة الطفل.
من خلال JAVAP -C ، يمكننا أن نفهم بشكل مباشر سبب وجود فرق كبير بين سمات ورث الأساليب والأساليب. إذا أزلنا طريقة إعادة كتابة المعلومات لابن الفئة الفرعية في المثال أعلاه ، فسيتم استدعاء طريقة المعلومات الخاصة بالفئة الأصل في هذا الوقت ، لأنه عند التجميع ، سيتم نقل طريقة المعلومات الخاصة بالفئة الأصل إلى الفئة الفرعية ، وسيتم ترك متغير عضو السمعة في الفئة الأصل وعدم نقله. وبهذه الطريقة ، فإن الفئة الفرعية والفئة الأم لها متغيرات مثيل مع نفس الاسم. إذا أعادت الفئة الفرعية إعادة كتابة طريقة الفئة الأصل التي تحمل نفس الاسم ، فستقوم طريقة الفئة الفرعية بالكتابة تمامًا عن طريقة فئة الأصل (كما هو الحال بالنسبة لسبب تصميم Java مثل هذا ، لست واضحًا جدًا). يمكن أن توجد المتغيرات ذات الاسم نفسه ولا تكتب في نفس الوقت. ستشكل الفئات الفرعية من الأساليب مع نفس الاسم تمامًا طريقة الاسم من فئة الأصل.
بشكل عام ، للحصول على متغير مرجعي ، عند الوصول إلى متغير مثيل للكائن الذي يشير إليه من خلال المتغير ، تعتمد قيمة متغير المثيل على النوع عند الإعلان عن المتغير ، وعند الوصول إلى طريقة الكائن الذي يشير إليه من خلال المتغير ، يعتمد سلوك الطريقة على نوع الكائن الذي يشير إليه بالفعل.
أخيرًا ، سأراجعها بحالة صغيرة:
Package com.zlc.array ؛ class Animal {int Age ؛ Public Animal () {} Public Animal (int age) {// todo conger tudo tudo coll this.age = age ؛ } void run () {system.out.println ("Animal Run"+Age) ؛ }} class class يمتد الحيوان {int age ؛ اسم السلسلة الكلب العام (int age ، اسم السلسلة) {// todo constructor constructor this.age = age ؛ this.name = name ؛ } Override void run () {system.out.println ("dog run"+age) ؛ }} الفئة العامة testextends {public static void main (string [] args) {Animal Animal = new Animal (5) ؛ System.out.println (Animal.age) ؛ Animal.run () ؛ كلب الكلب = كلب جديد (1 ، "Xiaobai") ؛ system.out.println (dog.age) ؛ dog.run () ؛ Animal Animal2 = New Dog (11 ، "Wangcai") ؛ System.out.println (Animal2.age) ؛ Animal2.Run () ؛ Animal3 ؛ Animal3 = كلب ؛ System.out.println (Animal3.age) ؛ Animal3.Run () ؛ }} إذا كنت ترغب في الاتصال بالطريقة الفئة الأصل: يمكنك الاتصال بها من خلال Super ، ولكن الكلمة الرئيسية الفائقة لا تشير إلى أي كائن ، ولا يمكن استخدامها كمتغير مرجعي حقيقي. يمكن للأصدقاء المهتمين دراستها بنفسك.
ما سبق هي متغيرات وطرق مثال. متغيرات الفصل وأساليب الفصل أبسط بكثير ، لذلك باستخدام أسماء الفصول مباشرة. الطرق أكثر ملاءمة بكثير ولن تواجه الكثير من المتاعب.
4. استخدام المعدلات النهائية (وخاصة استبدال الماكرو)
(1) يمكن تعديل المتغيرات inal. بعد تعيين المتغير الذي تم تعديله بواسطة النهائي قيمة أولية ، لا يمكن تعيينه مرة أخرى.
(2) يمكن لـ Inal تعديل الطريقة ، ولا يمكن إعادة كتابة الطريقة المعدلة النهائية.
(3) يمكن لـ Inal تعديل الفئات ، والفئات التي تم تعديلها بواسطة النهائي لا يمكن أن تستمد الفئات الفرعية.
يجب عرض القيمة الأولية المحددة التي يجب تعديل المتغير حسب النهائي:
على سبيل المثال متغيرات تعديلها النهائي ، لا يمكن تعيين القيمة الأولية إلا في المواضع الثلاثة التالية.
(1) حدد القيمة الأولية عند تحديد متغير المثيل النهائي.
(2) حدد القيمة الأولية لمتغير المثيل النهائي في كتلة غير منتظمة.
(3) حدد القيمة الأولية لمتغير المثيل النهائي في المنشئ.
سيتم ذكرهم في النهاية في مُنشئ التهيئة.
بالنسبة لمتغيرات الفئة المحددة مع النهائي: لا يمكن تعيين القيم الأولية إلا في مكانين محددين.
(1) حدد القيمة الأولية عند تحديد متغير الفئة النهائية.
(2) حدد القيمة الأولية لمتغير الفئة النهائية في كتلة ثابتة.
كما تتم معالجتها بواسطة برنامج التحويل البرمجي ، على عكس متغيرات المثيل ، يتم ذكر جميع متغيرات الفئة لتعيين القيم الأولية في كتل ثابتة ، بينما يتم ذكر متغيرات المثيل للمقدمات.
هناك ميزة أخرى من متغيرات الفئة المعدلة بواسطة Final ، والتي هي "استبدال الماكرو". عندما يفي متغير الفئة المعدلة بالقيمة الأولية عند تحديد المتغير ، يمكن تحديد القيمة الأولية أثناء التجميع (على سبيل المثال: 18 ، "AAAA" ، 16.78 وكميات مباشرة أخرى) ، فإن متغير الفئة المعدل حسب النهائي ليس متغيرًا ، وسيعامل النظام على أنه "متغير ماكرو" (وهو ما ندعو غالبًا إلى ثابت). إذا كان يمكن تحديد القيمة الأولية أثناء التجميع ، فلن يتم ذكرها في الكتلة الثابتة للتهيئة ، وسيتم استبدال القيمة الأولية مباشرة بالمتغير النهائي في تعريف الفئة. دعونا نعطي مثالاً على العمر ناقص سنة:
حزمة com.zlc.array ؛ الفئة testStatic {// Class Member Demo TestStatic مثيل Final Static TestStatic Demo = New TestStatic (15) ؛ // عضو الفئة العمر النهائي static int = 20 ؛ // مثيل المتغير curage int curage ؛ TestStatic العام (int years) {// todo todo tuto crage curage = age - years ؛ }} اختبار الفئة العامة {public static void main (string [] args) {system.out.println (testStatic.demo.curage) ؛ TestStatic Static1 = اختبار جديد (15) ؛ System.out.println (static1.curage) ؛ }} في هذا الوقت ، يتم تعديل العمر حسب النهائي ، لذلك عند التجميع ، تصبح جميع الأعمار في الفئة الأصل 20 ، وليس متغيرًا ، بحيث يمكن أن تفي نتيجة الإخراج بتوقعاتنا.
خاصة عند مقارنة السلاسل ، يمكن عرضها أكثر
حزمة com.zlc.array ؛ الفئة العامة testString {Static String static_name1 = "java" ؛ Static String static_name2 = "me" ؛ سلسلة ثابتة Statci_Name3 = static_name1+static_name2 ؛ Final Static String Final_static_name1 = "java" ؛ سلسلة ثابتة Final_static_name2 = "Me" ؛ // أضف نهائيًا أم لا ، يمكن استبداله بماكرو في المقدمة. Final String Final_statci_name3 = Final_static_name1+Final_static_name2 ؛ public static void main (string [] args) {string name1 = "java" ؛ string name2 = "me" ؛ name name3 = name1+name2 ؛ // (1) system.out.println (name3 == "javame") ؛ // (2) system.out.println (testString.statci_name3 == "javame") ؛ // (3) system.out.println (testString.final_statci_name3 == "javame") ؛ }} لا يوجد شيء يمكن قوله حول استخدام أساليب التعديل النهائي والفئات ، فقط أنه لا يمكن إعادة كتابة المرء بواسطة الفئات الفرعية (مثل القطاع الخاص) ، والآخر لا يمكن أن يستمد الفئات الفرعية.
عند تعديل المتغيرات المحلية مع النهائي ، تتطلب Java أن يتم تعديل المتغيرات المحلية التي يمكن الوصول إليها بواسطة الفئات الداخلية مع النهائي. هناك سبب. بالنسبة للمتغيرات المحلية العادية ، يبقى نطاقها ضمن الطريقة. عندما تنتهي الطريقة ، يختفي المتغير المحلي ، لكن قد يولد الفئة الداخلية "إغلاقًا" ضمنيًا ، مما يؤدي إلى بقاء المتغير المحلي منفصلًا عن الطريقة التي توجد بها.
في بعض الأحيان ، سيكون مؤشر الترابط جديدًا في طريقة ما ، ثم يتم استدعاء المتغير المحلي للطريقة. في هذا الوقت ، يجب الإعلان عن متغير التغيير على أنه تم تعديله النهائي.
5. طريقة حساب ذاكرة إشغال الكائن
استخدم أساليب Freememory () و TotalMemory () و MaxMemory () في فئات Java.lang.Runtime لقياس حجم كائن Java. عادة ما يتم استخدام هذه الطريقة عندما تحتاج الكثير من الموارد إلى تحديدها بدقة. هذه الطريقة غير مجدية تقريبًا لتنفيذ ذاكرة التخزين المؤقت لنظام الإنتاج. ميزة هذه الطريقة هي أن نوع البيانات مستقل عن الحجم ، ويمكن أن تحصل أنظمة التشغيل المختلفة على الذاكرة.
يستخدم واجهة برمجة تطبيقات الانعكاس لاجتياز التسلسل الهرمي لمتغيرات الأعضاء للكائن وحساب حجم جميع المتغيرات الأصلية. لا يتطلب هذا النهج الكثير من الموارد ويمكن استخدامه للتطبيقات المخزنة مؤقتًا. العيب هو أن حجم النوع الأصلي مختلف وأن تطبيقات JVM مختلفة لها طرق حسابية مختلفة.
بعد JDK5.0 ، توفر واجهة برمجة تطبيقات الأجهزة طريقة getObjectsize لحساب حجم الذاكرة الذي يشغله الكائن.
بشكل افتراضي ، لا يتم حساب حجم الكائن المشار إليه. من أجل حساب الكائن المشار إليه ، يمكنك استخدام التفكير للحصول عليه. الطريقة التالية هي تطبيق منصوص عليه في المقالة أعلاه يحسب حجم الكائن المرجعي:
حجم الطبقة العامة {static Instrictation Inst ؛ / ** تهيئة Agent*/ public static void premain (string AgentArgs ، Instractation Instp) {Inst = Instp ؛ } /*** إرجاع حجم الكائن بدون كائنات فرعية عضو. * param o object للحصول على حجم * size كائن RETURN */public static static alseof (object o) {if (inst == null) {رمي جديد aluvalstateException ("لا يمكن الوصول إلى بيئة الأجهزة. } return Inst.GetObjectSize (O) ؛ } /** * يحسب الحجم الكامل للكائن المتكرر على * الرسم البياني للتسلسل الهرمي. * كائن param لحساب حجم * @RETURN SIZE */ public static static longsizeof (Object OBJ) {map <object ، object> agted = new IdentityHashMap <object ، object> () ؛ مكدس <bount> stack = مكدس جديد <Object> () ؛ نتيجة طويلة = internalsizof (obj ، stack ، زارها) ؛ بينما (! stack.isempty ()) {result += internalSizeOf (stack.pop () ، stack ، assed) ؛ } yoursed.clear () ؛ نتيجة العودة } skipObject الثابتة الخاصة (الكائن OBJ ، خريطة <كائن ، كائن> زيارته) {if (OBJ stiter string) {// تخطي السلسلة الداخلية إذا (obj == ((سلسلة) obj) .Intern ()) {return true ؛ }} return (obj == null) // skip esbored object || زيارة. containskey (OBJ) ؛ } private static internalsistizof (Object OBJ ، stack <Object> stack ، MAP <Object ، Object> تمت زيارته) {if (skipObject (obj ، terged)) {return 0 ؛ } زيارة. نتيجة طويلة = 0 ؛ // الحصول على حجم الكائن + المتغيرات البدائية + نقاط الأعضاء نتيجة + = sizeofagent.sizeof (OBJ) ؛ // معالجة جميع عناصر الصفيف clazz = obj.getClass () ؛ if (clazz.isarray ()) {if (clazz.getName (). length ()! = 2) {// تخطي نوع النوع البدائي int length = array.getLength (obj) ؛ لـ (int i = 0 ؛ i <length ؛ i ++) {stack.add (array.get (obj ، i)) ؛ }} نتيجة الإرجاع ؛ } // معالجة جميع حقول الكائن بينما (clazz! = null) {field [] fields = clazz.getDeclaredFields () ؛ لـ (int i = 0 ؛ i <fields.length ؛ i ++) {if (! modifier.isStatic (fields [i] .getModifiers ())) {if (fields [i] .gettype (). isprimitive ())) {متابعة ؛ // تخطي الحقول البدائية} آخر {fields [i] .SetAccible (true) ؛ جرب {// الكائنات المراد تقديرها يتم وضعها على كائن الكائن oubpertoadd = الحقول [i] .get (obj) ؛ if (objectToadd! = null) {stack.add (objectToadd) ؛ }} catch (inchalicalAccessException ex) {assert false ؛ }}}}} clazz = clazz.getSuperClass () ؛ } نتيجة الإرجاع ؛ }}