إذا استدعينا طريقة getPackage على كائن الفئة ، فيمكننا الحصول على كائن الحزمة الذي يصف الحزمة التي توجد فيها الفئة (يتم تعريف فئة الحزمة في java.lang). يمكننا أيضًا استخدام اسم الحزمة للحصول على كائن الحزمة من خلال استدعاء الطريقة الثابتة getPackage أو استدعاء الطريقة الثابتة getPackages (التي تُرجع مجموعة مكونة من جميع الحزم المعروفة في النظام). يمكن أن تُرجع طريقة getName الاسم الكامل للحزمة.
يختلف استخدام كائنات الحزمة تمامًا عن أنواع الانعكاس الأخرى ، أي أنه لا يمكننا إنشاء أو معالجة الحزم في وقت التشغيل. يمكننا استخدام كائنات الحزمة للحصول على معلومات حول الحزم ، مثل الغرض من الحزمة ، التي أنشأت الحزمة ، وإصدار الحزمة ، وما إلى ذلك. سنقوم بتأجيل هذه المحتويات حتى سنناقشها بالتفصيل لاحقًا.
تسمية الحزمة
يجب أن تتجنب أسماء الحزم التعارض مع الحزم الأخرى ، لذا فإن اختيار اسم ذي معنى وفريد من نوعه هو جانب مهم لتصميم الحزمة. ومع ذلك ، يقوم المبرمجون في جميع أنحاء العالم بتطوير حزم ، ولا توجد طريقة لمعرفة من يستخدم اسم الحزمة ، لذلك اختيار اسم الحزمة الوحيد هو مشكلة. إذا قررنا أن الحزمة تستخدم فقط داخل مؤسستنا ، فيمكننا الحصول على محكم داخلي لضمان عدم وجود تعارض في الاسم بين المشاريع.
لكن بالنسبة للعالم كله ، هذا النهج ليس عمليًا. معرفات الحزمة كلها أسماء بسيطة ، وطريقة أفضل للتأكد من أن اسم الحزمة هو استخدام اسم مجال الإنترنت. إذا كانت الشركة التي نعمل فيها هي Magic.lnc واسم نطاق الشركة هو Magic C.com ، فيجب أن يكون إعلان حزمة السمات:
حزمة com.magic.attr ؛
لاحظ أن العناصر المكونة لاسم المجال هنا مرتبة بترتيب عكسي لاسم المجال التقليدي.
إذا اعتمدنا هذا المصطلح ، فلن تتعارض أسماء الحزم التي نستخدمها مع أي شخص آخر باستثناء الصراع المحتمل داخل مؤسستنا. إذا كان هناك بالفعل تعارض داخل مؤسستنا (ربما مؤسسة كبيرة) ، فيمكننا استخدام أسماء المجالات الأكثر تحديدًا لمزيد من التأهل. العديد من الشركات الكبيرة لديها نادي فرعي داخلي ، مثل شرق وأوروبا ، والتي يمكن استخدامها لزيادة تأهيل اسم الحزمة:
حزمة corn.magic.japan.attr ؛
قد يؤدي استخدام هذا الحل إلى جعل اسم الحزمة طويلًا جدًا ، لكنه آمن نسبيًا. لن يختار المبرمجون الذين يستخدمون هذه التقنية نفس اسم الحزمة ، ولن يختار المبرمجون الذين لا يستخدمون هذه التقنية الاسم الذي نستخدمه.
حزمة محتوى
يجب تصميم محتويات الحزمة بعناية بحيث تتضمن فقط فئات وواجهات ذات صلة وظيفيًا. يمكن للفصول في الحزمة الوصول بحرية إلى الأعضاء غير الخاصة من الفئات الأخرى في الحزمة ، وقد يكون لدى بعض الفصول أذونات كافية للوصول إلى التفاصيل الداخلية للفئات الأخرى. من أجل تجنب مثل هذه الفئات من أعضاء الفصل الخاطئ ، نحتاج إلى حماية أعضاء الفصل. يمكن الوصول إلى أي عضو لم يتم إعلانه على أنه خاص من قبل جميع الأنواع الأخرى في نفس الحزمة ، لذلك قد تكون أي فئات غير ذات صلة أكثر تنسيقًا مما نتوقع.
توفر الحزم أيضًا تجميعًا منطقيًا للمبرمجين الذين يبحثون عن واجهات وفئات مفيدة. تجعل الحزم المكونة من فصول غير ذات صلة من الصعب على المبرمجين معرفة الواجهات والفئات المفيدة ، ويمكن للتجميع المنطقي للفئات مساعدة المبرمجين على إعادة استخدام الكود لأن المبرمجين يمكنهم العثور على ما يحتاجون إليه بسهولة أكبر من خلال التجميع المنطقي. إذا كانت الحزمة تحتوي فقط على مجموعات النوع المرتبطة بإحكام ، فهذا يعني أنه يمكننا إعطاء النوع بعض الأسماء الأكثر سهولة لتجنب تعارضات الاسم.
يمكن أن تكون الحزم متداخلة. على سبيل المثال ، java.lang هي حزمة متداخلة حيث تتداخل الحزمة lang في حزمة أكبر Java ، في حين أن الحزمة J Ava تحتوي أيضًا على بعض الحزم الأخرى. التعشيش يجعل الحزم ذات الصلة تشكل نظام تسمية مع بنية هرمية.
على سبيل المثال ، لإنشاء مجموعة من الحزم للأنظمة التكيفية مثل الشبكات العصبية والخوارزميات الوراثية ، يمكننا تسمية الحزم بأسماء مفصولة DOT لإنشاء حزم متداخلة:
حزمة تكيفية. الشبكة العصبية
يقع الملف المصدر الذي يحتوي على بيان الإعلان أعلاه في حزمة Adaptive.nuralNet ، وحزمة exaptive.neuralnet نفسها هي مجموعة فرعية للحزمة التكيفية. قد تحتوي الحزمة التكيفية على بعض الفئات المتعلقة بالخوارزميات التكيفية العامة ، مثل فئات بيان مشكلة التعميم أو فئات القياس. تحتوي الحزم الموجودة في وضع أعمق في التسلسل الهرمي (مثل Adaptive.neu-Ralnet أو Adaptive.genetic) على فئات تتعلق بنوع معين من الخوارزمية التكيفية.
تعشش الحزم هو مجرد أداة لتنظيم الحزم ذات الصلة ، ولا توفر أي حقوق وصول خاصة بين الحزم.
لا يمكن لبرنامج الفئة في الحزمة Adaptive.genetic الوصول إلى الأعضاء في حزمة Adaptive أو Adaptive.NuralNet التي لها حقوق الوصول إلى الحزمة ، ونطاق الحزمة ينطبق فقط على حزم محددة. يمكن أن يؤدي تعشيش الحزم إلى تجميع الحزم ذات الصلة ومساعدة المبرمجين في العثور على الفئة المطلوبة في المستوى المنطقي أكثر ارتباطًا ، ولكن بعد ذلك ، لا يجلب أي فوائد أخرى.
ملاحظات الحزمة
الحزمة يمكن أن يكون أيضا التعليقات التوضيحية. ولكن المشكلة هي أنه نظرًا لأن الحزم هي بنية تنظيمية بدون كيانات رمز المصدر وليس لها تعريف فعلي ، فلا يمكن تعليقها مثل الفئات أو الأساليب ، لذلك لا يمكن تحقيق شرح الحزمة إلا من خلال شرح بيان إعلان الحزمة في الملف المصدر. ومع ذلك ، لا يمكن أن يكون هناك سوى إعلان حزمة واحد في كل حزمة يمكن أن يكون لها تعليقات توضيحية تعمل عليها.
إذن كيف يمكنك التعليق على الحزم؟ في الواقع ، لا تجبر Java المبرمجين على استخدام بطريقة ما للتعامل مع قاعدة "بيان الحزمة المشروح الفردي". تتمثل الطريقة الموصى بها في إنشاء ملف يسمى Package-I nfo.java في دليل الحزمة ، حيث يتم تخزين فقط عبارات الحزمة وشروح الحزمة دون وضع أي شيء آخر. على سبيل المثال ، يبدو ملف info.java الحزمة لحزمة ATTR هكذا:
packagespec (اسم اثنين من "attr project" ، الإصدار = "1.0" developmentesite ("attr.project.org") DevelopmentModel ("Open-Source) Package ؛يتم استخدام PackagesPec و DevelopmentSite و Development OpmentModel لتعديل أنواع التعليقات التوضيحية. بالطبع ، لديهم استراتيجيات توفير وقت التشغيل. يجب تجميع ملف package-info.java مع ملفات مصدر أخرى في الحزمة.
نوصي بوضع جميع المعلومات المتعلقة بالحزم في ملف حزمة info.java. إذا قمت بذلك ، يمكنك وضع تعليقات المستندات في بداية الملف ، بحيث يتم شرح هذه المستندات كمستندات حزمة.
الوصول إلى الحزمة
عند الإعلان عن إمكانية الوصول إلى فصول المستوى الأعلى والواجهات ذات المستوى الأعلى في الحزم ، هناك خياران: الوصول إلى الحزمة (الحزمة) والوصول العام (العام). يمكن الوصول إلى الفئات أو الواجهات المعدلة مع الجمهور بواسطة رمز خارج الحزمة ، في حين أن الأنواع غير المزينة مع الجمهور لها نطاق الحزمة: يمكن الوصول إليها بواسطة رموز أخرى في نفس الحزمة ؛ لكنها مخفية للرموز خارج الحزمة ، حتى في رموز الحجز الفرعي. عند إعلان الأنواع ، يجب أن نعلن فقط تلك الأنواع التي يحتاجها المبرمجون الآخرون إلى استخدامها كجمهور ، وإخفاء تلك الأنواع التي تنتمي إلى تفاصيل تنفيذ الحزمة. توفر لنا هذه التقنية مرونة كبيرة ، وبما أن المبرمجين لا يعتمدون على هذه الأنواع من تفاصيل التنفيذ التي لا يمكنهم الوصول إليها ، يمكننا تغييرها بحرية عندما نريد تغيير تفاصيل التنفيذ.
يمكن الوصول إلى أعضاء الفصل الذين لم يتم إعلانهم على أنهم عام أو محمي أو خاص بواسطة أي رمز داخل الحزمة ، ولكن يتم إخفاءه من خارج الحزمة. وبعبارة أخرى ، فإن معدل الوصول الافتراضي هو "حزمة" ، باستثناء أعضاء الواجهة ، ومعدل الوصول الافتراضي الخاص بهم هو "عام".
يمكن الوصول إلى الحقول أو الأساليب التي لم يتم إعلانها الخاصة داخل الحزمة بواسطة جميع التعليمات البرمجية الأخرى في تلك الحزمة ، لذلك تعتبر الفئات في نفس الحزمة "ودية" أو "موثوقة". يتيح لنا ذلك تحديد إطار عمل يجمع بين الكود المحدد مسبقًا ورمز العنصر النائب ، حيث يتم تجاوز رمز العنصر النائب بواسطة فئة فرعية من فئة الإطار. يمكن أن تستخدم الرموز المحددة مسبقًا معدلات الوصول إلى الحزمة بحيث يمكن للرموز التعاونية الأخرى داخل الحزمة الوصول إليها مباشرة ، ولكن بالنسبة للمستخدمين خارج الحزم ، لا يمكن الوصول إلى هذه الرموز. ومع ذلك ، فإن الحالات الفرعية للحزم التي توجد فيها هذه الرموز ليست موثوقة والعكس بالعكس. على سبيل المثال ، لا يمكن الوصول إلى رمز معدل الوصول إلى الحزمة في الحزمة DIT بواسطة الرمز في حزمة الطفل dit.dat ، والعكس صحيح.
لذلك ، يحدد كل نوع ثلاثة عقود مختلفة:
.publi. العقد: يحدد الوظيفة الرئيسية للنوع.
العقد المحمي: يحدد الوظائف المتاحة للفئات الفرعية لأغراض التخصص.
. كل هذه العقود تتطلب دراسة وتصميم بعناية.
طريقة الوصول والغطاء
يمكن كتابة الطرق التي يمكن الوصول إليها فقط في فئات فائقة في الفئات الفرعية. إذا تعذر الوصول إلى طريقة في الفئة الفائقة ، فلا يمكن تجاوز الطريقة في الفئة الفرعية حتى لو كانت الطريقة في الفئة الفرعية لها نفس اسم الطريقة. عندما يتم استدعاء طريقة في وقت التشغيل ، ينظر النظام في إمكانية وصوله وبالتالي يحدد تنفيذها.
يتم شرح المثال التالي الذي تم إنشاؤه خصيصًا بشكل أكثر وضوحًا. لنفترض أننا نعلن عن فئة القاعدة التجريدية في حزمة P1:
حزمة P1 ؛ {ab abab abab public classesbasebase private void pri () {print ("stractbase.pri ()"):} void pac () {print ("stractbase.pac ()") ؛ } void pro () {print ("stractbase.pro ()") ؛ } public void pub () {print ("stractbase.pub ()") ؛} public final void show () pri () ؛ PAC () ؛ Pro () ؛ حانة()؛ }}في هذه الفئة ، نحدد 4 طرق ، ولكل منها معدل وصول مختلف ، ويحدد جسم الطريقة نفسه فقط. تُظهر الطريقة التي تُظهر هذه الطرق الأربعة على الكائن الحالي بدوره. عند تطبيق هذه الطريقة على كائنات فئة فرعية مختلفة ، يمكن أن يفسر أي تنفيذ هذه الأساليب.
الآن ، نحدد Class Concretel ، الذي يمتد فئة BustractBase ، ولكنه يقع في حزمة P2:
حزمة P2 ؛ استيراد p1.abstractbase الفئة العامة concretel يمتد الملخص {public void pri () {print ("concretel.pri ()") ؛} void pac () {print ("concretel.pac ()") ؛} public void pro () {print ("concretel.pro () pub () {print ("concretel.pub ()") ؛}}يتم إعادة تشكيل الطرق الأربعة في الفئة الفائقة في هذه الفئة ويتم تغيير تطبيقاتها ، والتي تبلغ عن أنها تنتمي إلى فئة Con-Cretel. في الوقت نفسه ، تم تغيير حقوق الوصول الخاصة بهم إلى الأماكن العامة حتى يتم الوصول إلى رمز آخر. تنفيذ الرمز التالي
concretel (). show ():
سيتم إنشاء الإخراج التالي:
AbstractBase.PRI () AbstractBase.Pac () Concretel.Pro () Concretel.pub ()
نظرًا لأنه لا يمكن الوصول إلى الطريقة الخاصة PRI بواسطة فئات فرعية (أو فئات أخرى) ، فإن طريقة العرض تدعو دائمًا إلى تنفيذ طريقة PRI في فئة AbstractBase. لا يمكن الوصول إلى طريقة PAC مع أذونات الوصول إلى الحزمة في فئة AbstractBase بواسطة Concretel ، وبالتالي لا يمكن لتنفيذ طريقة PAC في فئة Concretel تجاوز التعريف في فئة BustrictBase ، وبالتالي فإن طريقة العرض تستدعي طريقة AbstractBase.Pac. يمكن الوصول إلى طريقة PRO وطريقة الحانة في فئة Concretel ويمكن الكتابة أيضًا ، وبالتالي فإن طريقة العرض تستدعي تنفيذ هاتين الطريقتين في فئة Concretel.
اتبع Foot Way Class Class2 لتوسيع نطاق الفئة ، ثم نضعه في نفس الحزمة P1 مثل فئة AbstractBase ":
حزمة P1 ؛ استيراد p2.concretel الفئة العامة concrete2 يمتد concretel {public void pri () {print ("concrete2.pri () ؛} public void pac () {print (" concrete2 }نظرًا لأن الأساليب في Concretel لها حقوق وصول عامة ، يمكن الوصول إليها في Concrete2 ، وكل طريقة في Concrete2 تغطي أساليبها المقابلة بشكل منفصل. بالإضافة إلى ذلك ، نظرًا لأن Concrete2 و AbstractBase موجودون في نفس الحزمة ، يمكن أيضًا الوصول إلى Method AbstractBase.Pac في Concrete2 ، ويمكن تجاوز Method Concrete2.Pac. استدعاء طريقة العرض على كائن Concrete2 ، ونتيجة الطباعة هي كما يلي:
AbstractBase.PRI () concrete2.pac () concrete2.pro () concrete2.pub ()
أخيرًا ، نحدد الفئة Concrete3 لتوسيع Class Concrete2 ووضعها في الحزمة P3:
حزمة P3 استيراد P1.Concrete2 ؛ يمتد concrete3 الفئة العامة Concrete2 {public void pri () {print (استدعاء طريقة العرض على كائن Concrete3 ، ونتيجة الطباعة هي كما يلي:
AbstractBase.Pri () Concrete3.Pac () Concrete3.Pro () Concrete3.pub ()
هنا concrete3.pac يبدو أنه يتجاوز طريقة الملخص غير الممكنة. pac ، ولكن في الواقع ، فإن الطريقة concrete3.pac تتجاوز الطريقة concrete2.pac ، و method concrete2.pac يتجاوز method ussstructbase.pac ، لذلك method concrete3.p باك غير مبدّر عن الطريقة التجريبية. pac. من خلال إعادة تشغيل طريقة PAC في الفئة Concrete2 باعتبارها ذات أذونات وصول عامة ، يمكن الوصول إليها وإفراطها بواسطة أي فئة فرعية.
كائنات الحزمة والمواصفات
عادة ما تنفذ الحزم بعض المواصفات ، وعادة ما تكون من المؤسسة. تختلف كائنات الحزمة عن أنواع الانعكاس الأخرى ولا يمكن استخدامها لإنشاء الحزم أو تشغيلها ، ولكن يمكن أن تعمل فقط كقاعدة معرفة لتوفير المعلومات ، والتي توفر معلومات حول المواصفات التي تنفذها الحزمة (العنوان ، والبائع ، ورقم الإصدار) ومعلومات حول تنفيذ الحزمة نفسها (العنوان ، ورقم البائع ، ورقم الإصدار من الحزمة). على الرغم من أن الحزم تأتي عادة من المنظمات الفردية ، إلا أنه يمكن تحديد المواصفات التي تنفذها (مثل مكتبات التحليل الإحصائي) من قبل المنظمات الأخرى. قد تحتاج البرامج التي تستخدم الحزم إلى معرفة إصدار المواصفات التي تنفذها الحزمة ، بحيث يمكن استخدام الوظائف المحددة فقط في إصدار معين. وبالمثل ، قد تحتاج هذه البرامج أيضًا إلى معرفة إصدار التنفيذ الذي يتم توفيره لها ، وذلك أساسًا للتعامل مع العيوب المحتملة في الإصدارات المختلفة. تتيح بعض الطرق الرئيسية لفئة الحزمة الوصول إلى هذه المعلومات:
・ stri ng ng getName (): إرجاع اسم الحزمة.
. إذا كان العنوان غير معروف ، فالارتداد فارغًا ،
. إذا كانت معلومات الإصدار غير معروفة ، فالارتداد فارغًا ،
. إذا كان المورد غير معروف ، فالارتداد فارغًا ،
. إذا كان العنوان غير معروف ، فإنه يعيد NULL ، ・ سلسلة عامة getImplementation (): إرجاع سلسلة تصف معلومات الإصدار للتنفيذ المقدم من الحزمة. إذا كانت معلومات الإصدار غير معروفة ، فإنها تُرجع خالية ،
・ السلسلة العامة getImplementationVendor (): إرجاع اسم المنظمة (البائع) الذي يوفر التنفيذ. إذا كانت المنظمة غير معروفة ، فالارتداد الفارغ ،
على سبيل المثال ، إذا قمنا باستخراج هذه المعلومات من حزمة Java.lang في نظامنا ، فسوف نحصل على النتائج التالية:
عنوان المواصفات: Java Platform API ، الإصدار المواصفات: 1.4 مواصفات بائع: Sun Microsystems ، Inc. عنوان التنفيذ: Java Runtime Environment إصدار تنفيذ: 1.5.0_02 بائع التنفيذ: Sun Microsystems ، Inc.
يتكون رقم الإصدار الكنسي من أرقام غير سالبة مفصولة بواسطة محددات الفترة ، مثل "" 2.0 "أو "111 .0.12". يتيح لنا هذا النمط استدعاء طريقة isCompatibleWith لمقارنة رقم الإصدار الذي يتبع هذا النمط برقم إصدار الحزمة. إذا كان رقم إصدار الحزمة أكبر من أو يساوي رقم إصدار الخلف ، فسيتم إرجاع الطريقة بشكل صحيح. تقارن هذه المقارنة فقط رقمًا مفصلاً في وقت واحد. إذا كان أي من هذه الأرقام أصغر من الموضع المقابل في رقم الإصدار الذي تم تمريره ، فإن الإصدارين غير متوافقين. إذا كان أحد أرقام الإصدار أطول من الآخر ، فسيتم اعتبار الجزء المفقود في أرقام الإصدار القصيرة صفرًا. على سبيل المثال ، إذا كان رقم الإصدار الكنسي للحزمة هو "1.4" ونقارنه بـ "1.2" أو "1.3.1". أو ".1.81. ، فسيتم إرجاع True ؛ ولكن إذا ما قورنت مع "1.4.2". أو ".5" ، سيتم إرجاع خطأ. هذا الاستنتاج يتم استخلاصه لأن آلية المقارنة هذه تفترض أن إصدار المواصفات متوافق للخلف.
لا يوجد تنسيق محدد لرقم إصدار التنفيذ ، لأن المؤسسات المختلفة التي توفر التنفيذ ستحدد إصدار التنفيذ بشكل مختلف. المقارنة الوحيدة التي يمكن إجراؤها بين إصدارات التنفيذ هي اختبار ما إذا كان الإصدار هو نفسه ، حيث لا يوجد افتراض للتوافق المتخلف.
يمكن إغلاق الحزمة ، مما يعني أنه لم يعد بإمكان الطبقات إضافة إلى الحزمة. يمكن أن تحتوي الحزم غير المعروفة على فئات من مواقع مختلفة متعددة في مسار البحث في الفصل ، في حين يجب أن تأتي محتويات الحزمة المختومة من نفس الموقع - إما أرشيف معين أو موقع محدد بواسطة عنوان URL. هناك طريقتان لتحديد ما إذا كانت الحزمة مغلقة:
.
. إذا كان لا يمكن تحميل الفئة الموجودة في الحزمة من عنوان URL معين ، أو لم يتم إغلاق الحزمة ، ثم يتم إرجاع خطأ ، وعادة ما يتم توفير معلومات المواصفات والتنفيذ الخاصة بالحزمة كجزء من ملف البيان المخزّن مع الحزمة - على سبيل المثال كجزء من ملف البيان في أرشيف Java (جار) ، كما هو موضح في القسم 25.9.2 ، "Archive File Java.jar". عندما يتم تحميل فئة في حزمة ، يتم قراءة هذه المعلومات من قبل الشخص. يمكن لمحمل Classload تحديد كائن الحزمة ديناميكيًا للفصل الذي يريد تحميله:
. الحزمة المحمية DENEPACKAGE (اسم السلسلة ، Spectitle السلسلة ، مراقبة السلسلة ، SPECVENDOR ، سلسلة intltitle ، انحراف السلسلة ، السلسلة المؤقتة ، قاعدة url sealbase): ستُرجع هذه الطريقة كائن الحزمة مع اسم الحزمة المحدد وقيمة المواصفات وقيمة التنفيذ بواسطة الاقتباس المقابل. إذا كانت قاعدة بيانات المعلمة فارغة ، فسيتم إغلاق الحزمة ، وإلا يتم إغلاق الحزمة لعنوان URL هذا: يجب تحديد كائن حزمة الفئة قبل تعريف الفصل ، ويجب أن يكون اسم الحزمة فريدًا في محمل الفئة. إذا تم تكرار اسم الحزمة مع الاسم الحالي ، فسيتم طرح العمل 11EGA1ArgumentException.
يمكننا استدعاء طريقة getPackage لكائن الفئة من الفئة المحددة للحصول على كائن الحزمة في هذه الفئة. يمكننا أيضًا الاتصال بـ static package.getPackage باستخدام اسم الحزمة المحدد للحصول على كائن الحزمة ، أو الاتصال بـ static package.getPackages ، والتي ستعيد مجموعة الحزمة المكونة من جميع الحزم المعروفة حاليًا إلى تحميل الفئة. ترتبط كلتا الطريقتين بموادي الفئة الذي يستدعي رمزهما ، لأن هذه الرموز ستستدعي أساليب GetPackage أو GetPackages الخاصة بـ Loader الخاصة بهم. ستبحث طرق اللوادر الفئة هذه عن محمل فئة محدد وجميع لوادرها من الفئة الأم ، وإذا لم يتم إجراء إعدادات لعملية تحميل الفئة الحالية ، فسيتم استخدام محمل فئة النظام في هذا الوقت. لاحظ أنه إذا كانت الحزمة غير معروفة ، فسيتم إرجاع طريقة ClassLoader NULL لأنه لم يتم تحميل أي نوع في الحزمة في هذا الوقت.