(1) أنواع الواجهة المتعلقة بالانعكاس + الجينات
java.lang.reflect.Type: الواجهة الرئيسية المشتركة لجميع الأنواع في لغة جافا
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType
1. اكتب الواجهة الفرعية المباشرة
أربعة أنواع من الواجهات: ParameterizedType وGenericArrayType وTypeVariable وWildcardType
ParameterizedType: يمثل نوعًا ذو معلمات، مثل Collection
GenericArrayType: يمثل نوع الصفيف الذي يكون نوع العنصر الخاص به عبارة عن نوع ذو معلمات أو متغير النوع
TypeVariable: هي الواجهة الرئيسية المشتركة لأنواع مختلفة من المتغيرات
WildcardType: يمثل تعبير نوع حرف بدل، مثل ?، ? يمتد الرقم، ? حرف البدل هو كلمة: إنه "حرف بدل"]
2. النوع ينفذ الفئات الفرعية مباشرة: فئة الفصل
3. واجهة java.lang.reflect.Type
تشير جميع أنواع النوع إلى: الأنواع الأولية (الأنواع الأولية) [المقابلة للفئة]، والأنواع ذات المعلمات (الأنواع ذات المعلمات) [المقابلة لـ ParameterizedType]، وأنواع المصفوفات (أنواع المصفوفات) [المقابلة لـ GenericArrayType]، ومتغيرات النوع (متغيرات النوع) [ المقابلة لـ TypeVariable ]، وأنواع البيانات الأساسية (الأنواع الأولية) [لا تزال تتوافق مع الفئة]
4. واجهة java.lang.reflect.ParameterizedType
معنى نوع واجهة ParameterizedType
يمثل نوعًا ذو معلمات. على سبيل المثال: نوع ذو معلمات مثل Map
احصل على النوع الفعلي في النوع ذو المعلمات<>
بيان كود المصدر: Type[] getActualTypeArguments();
[ملاحظة] بغض النظر عن عدد مستويات التداخل <> الموجودة في <>، فإن هذه الطريقة تزيل فقط المستوى الأبعد <> ويتم استخدام المحتوى المتبقي كقيمة الإرجاع لهذه الطريقة.
طريقة E الثابتة العامة IV(
قائمة المصفوفات> آل 1،
قائمة المصفوفات آل 2،
قائمة المصفوفات آل 3،
رقم ArrayListexends> al4،
قائمة المصفوفات al5){}
ثم تكون كل معلمة بشكل عام من النوع البارامترى.
{1}. بالنسبة إلى ArrayList>، بعد الرجوع عبر getActualTypeArguments()، وبعد إزالة <> الأبعد، فإن النوع المتبقي هو ArrayList. ولذلك فإن نوع الإرجاع لهذه المعلمة هو ParameterizedType.
{2}. بالنسبة إلى ArrayList، بعد الرجوع عبر getActualTypeArguments()، وبعد إزالة <> الأبعد، يكون النوع المتبقي هو E. ولذلك فإن نوع الإرجاع لهذه المعلمة هو TypeVariable.
{3}. بالنسبة إلى ArrayList، بعد العودة من خلال getActualTypeArguments()، بعد إزالة <> الأبعد، النوع المتبقي هو String. لذلك فإن نوع الإرجاع لهذه المعلمة هو Class.
{4}. بالنسبة إلى ArrayListextends Number>، بعد الرجوع عبر getActualTypeArguments()، بعد إزالة <> الأبعد، يكون النوع المتبقي هو ExtendsNumber. ولذلك فإن نوع الإرجاع لهذه المعلمة هو WildcardType.
{5}. بالنسبة إلى ArrayList، بعد الرجوع عبر getActualTypeArguments()، وبعد إزالة <> الأبعد، يكون النوع المتبقي هو E[]. ولذلك فإن نوع الإرجاع لهذه المعلمة هو GenericArrayType.
لذلك، من الممكن الحصول على معلمات فعلية من أنواع مختلفة، لذلك من أجل التوحيد، يتم استخدام مصفوفة الفئة الأصلية المباشرة Type[] للاستقبال.
4. واجهة java.lang.reflect.GenericArrayType
معنى نوع واجهة GenericArrayType
يمثل نوع صفيف عام. على سبيل المثال: طريقة باطلة(ArrayList[] al){…}
[ملاحظة] <> لا يمكن أن يظهر في تهيئة المصفوفة، أي أنه لا يمكن أن يظهر <> بعد المصفوفة الجديدة، وإلا فلن يمر javac. لكنه جيد تمامًا كمتغير مرجعي أو معلمة لطريقة ما.
احصل على نوع العناصر في مصفوفة عامة
إعلان التعليمات البرمجية المصدر: اكتب getGenericComponentType();
[ملاحظة] بغض النظر عن عدد [] المتجاورة من اليسار إلى اليمين، فإن هذه الطريقة تزيل فقط أقصى اليمين [] ويتم استخدام المحتوى المتبقي كقيمة الإرجاع لهذه الطريقة.
لماذا نوع قيمة الإرجاع هو النوع؟
طريقة E الثابتة العامةV(String[] p1,E[] p2,ArrayList[] p3,E[][] p4){}{1}. بالنسبة إلى السلسلة[]، بعد العودة عبر getComponentType()، وبعد إزالة أقصى اليمين []، فإن النوع المتبقي هو String. لذلك فإن نوع الإرجاع لهذه المعلمة هو Class
{2}. بالنسبة إلى E[]، بعد الرجوع عبر getComponentType()، وبعد إزالة أقصى اليمين []، فإن النوع المتبقي هو E. ولذلك فإن نوع الإرجاع لهذه المعلمة هو TypeVariable
{3}. بالنسبة إلى ArrayList[]، بعد الرجوع عبر getComponentType()، وبعد إزالة أقصى اليمين []، فإن النوع المتبقي هو ArrayList. ولذلك فإن نوع الإرجاع لهذه المعلمة هو ParameterizedType
{4}. بالنسبة إلى E[]]، بعد العودة عبر getComponentType()، وبعد إزالة أقصى اليمين []، فإن النوع المتبقي هو E[]. ولذلك فإن نوع الإرجاع لهذه المعلمة هو GenericArrayType
5. واجهة java.lang.reflect.GenericArrayType
معنى نوع الواجهة TypeVariable
يمثل معلمات النوع أو تسمى أيضًا متغيرات النوع. على سبيل المثال: E في طريقة void(E e){} هو متغير النوع
يحصل على نوع الحد الأعلى العام المؤهل لمتغير النوع
بيان كود المصدر: Type[] getActualTypeArguments();
[ملاحظة] هذه مجرد الحدود العليا. والسبب هو أن متغيرات النوع يمكنها فقط استخدام الامتدادات للحد من الحدود (المتعددة) عند تعريفها. لا يمكن استخدام Super، وإلا فلن ينجح التجميع. في الوقت نفسه، يمتد يعطي الحد الأعلى لمتغيرات النوع.
لماذا يكون نوع الإرجاع مصفوفة؟ نظرًا لأنه يمكن تأهيل متغيرات النوع بحدود عليا متعددة بواسطة &، فهناك حدود عليا متعددة، لذا فإن نوع قيمة الإرجاع هو نوع المصفوفة [].
على سبيل المثال الطريقة التالية:
ثابت عام يمتد الخريطة & قابل للاستنساخ والتسلسل> طريقة EVI (E e) {…}الحد العلوي الأول لـ E هو Map، وهو نوع ParameterizedType
الحد العلوي الثاني لـ E قابل للاستنساخ، وهو من نوع الفئة
لذلك، من أجل التوحيد، نوع العنصر في مصفوفة قيم الإرجاع هو النوع
6. واجهة java.lang.reflect.WildcardType
معنى نوع الواجهة WildcardType
تعبير يمثل نوع البدل.
على سبيل المثال، void printColl(ArrayListal); في ?
[ملاحظة] وفقًا لتعليقات واجهة برمجة التطبيقات المذكورة أعلاه: في هذه المرحلة، يقبل تعبير حرف البدل فقط الحد العلوي أو الحد الأدنى، ويختلف هذا عما هو الحال عند تحديد متغير النوع، والذي يمكنه تحديد حدود عليا متعددة. لكن واجهة برمجة التطبيقات قالت إنه من أجل الحفاظ على قابلية التوسع، تتم كتابة نوع القيمة المرجعة هنا في شكل مصفوفة. في الواقع، حجم المصفوفة التي تم إرجاعها الآن هو 1
الحصول على نوع الحد الأعلى العام المؤهل لكائن تعبير أحرف البدل
بيان كود المصدر: Type[] getUpperBounds();
[ملاحظة] كما ذكرنا سابقًا، حجم المصفوفة في النوع[] الذي تم إرجاعه في هذه المرحلة هو 1. الكتابة كـ Type[ ] هي امتداد لترقية اللغة.
على سبيل المثال الطريقة التالية:
{1}. public static voidprintColl(ArrayListextends ArrayList> al){}
تعبير حرف البدل هو: ? ExtendsArrayList، بحيث يتبع هذا الامتداد الحد العلوي لـ ?، وهذا الحد العلوي هو نوع ParameterizedType.
{2}. public static voidprintColl(ArrayListextends E> al){}
تعبير حرف البدل هو: ? يمتد E، بحيث يتبع هذا الامتداد الحد العلوي لـ ?، وهذا الحد العلوي هو نوع TypeVariable
{3}.public static voidprintColl(ArrayListextends E[]> al){}
تعبير حرف البدل هو: ? يمتد E[]، بحيث يتبع هذا الامتداد الحد العلوي لـ ?، وهذا الحد العلوي من النوع GenericArrayType
{4}.public static voidprintColl(ArrayListextends Number> al){}
تعبير حرف البدل هو: ? يمتد الرقم، بحيث يتبع هذا الامتداد الحد العلوي لـ ?، وهذا الحد العلوي هو نوع الفئة
تم توحيده أخيرًا في النوع كنوع عنصر المصفوفة.
7. أصل النوع وواجهاته الفرعية
1. الأنواع قبل ظهور الأدوية الجنيسة
عندما لا تكون هناك أدوية عامة، يوجد فقط ما يسمى بالأنواع البدائية. في هذا الوقت، يتم تجريد جميع الأنواع البدائية من خلال فئة ملف البايت كود Class. يمثل الكائن الملموس لفئة Class نوعًا بدائيًا محددًا.
2. الأنواع بعد ظهور الأدوية الجنيسة
بعد ظهور الأدوية الجنيسة، تم توسيع أنواع البيانات. من الأنواع البدائية فقط، تم توسيع الأنواع ذات المعلمات، وأنواع متغيرة النوع، والأنواع ذات المعلمات المؤهلة العامة (بما في ذلك أحرف البدل + التعبيرات المؤهلة لأحرف البدل)، وأنواع المصفوفات العامة.
3. سبب عدم إمكانية توحيد الأنواع المرتبطة بالأسماء العامة مع الأنواع الأصلية في الفصل
[1] [سبب المحو العام]
في الأصل، يجب توحيد الأنواع التي تم إنشاؤها حديثًا + الأنواع البدائية في كائنات نوع ملف الرمز الثانوي الخاصة بها. ولكن بما أن الأدوية الجنيسة لم تكن في الأصل مكونًا في جافا. إذا تمت إضافة الأدوية العامة بالفعل، فهذا يتضمن تعديل مجموعة تعليمات JVM، وهو أمر قاتل للغاية.
[2] [كيفية تقديم الأدوية الجنيسة في جافا]
من أجل الاستفادة من الأدوية العامة دون تقديمها فعليًا، تستخدم Java آلية محو عامة لتقديم الأدوية العامة. يتم استخدام الأدوية العامة في Java فقط بواسطة المترجم javac لضمان أمان البيانات وتجنب مشكلة تحويل النوع القسري. ومع ذلك، بمجرد اكتمال التجميع، يتم مسح جميع الأنواع المتعلقة بالأدوية العامة.
[3]. [لا يمكن للفئة التعبير عن الأنواع المرتبطة بالأدوية العامة]
لذلك، يتم إرجاع الأنواع ذات المعلمات المتعلقة بالأسماء العامة، وأنواع متغيرات النوع، والأنواع ذات المعلمات المؤهلة العامة (بما في ذلك أحرف البدل + التعبيرات المؤهلة لأحرف البدل)، وأنواع المصفوفات العامة إلى نماذجها الأصلية ويتم تخزينها في ملف الرمز الثانوي، وجميعها أنواع أصلية بعد أن يتم مسح الأدوية العامة، ولا يوجد ملف بايت كود متوافق مع نوعه الخاص. ولذلك، لا يمكن توحيد الأنواع الموسعة حديثًا المتعلقة بالأدوية العامة في فئة الفئة.
(4) تمثيل الأنواع المتعلقة بالأدوية العامة في Java
من أجل تشغيل هذه الأنواع من خلال الانعكاس لتلبية احتياجات التطوير الفعلي، أضافت Java ParameterizedType وGenericArrayType وTypeVariable وWildcardType لتمثيل الأنواع التي لا يمكن تصنيفها في فئة Class ولكن لها نفس اسم النوع الأصلي.
(5) التعريف بالنوع: توحيد الأنواع المتعلقة بالجنس والأنواع البدائية Class
[سبب إدخال النوع]
من أجل قابلية تطوير البرنامج، تم تقديم واجهة Type أخيرًا كواجهة رئيسية عامة لـ Class وParameterizedType وGenericArrayType وTypeVariable وWildcardType. بهذه الطريقة، تقبل معلمة نوع النوع المعلمات الفعلية للأنواع الفرعية الخمسة المذكورة أعلاه أو أن نوع قيمة الإرجاع هو معلمة نوع النوع.
[سبب عدم وجود طريقة في واجهة الكتابة]
كما يتبين مما سبق، فإن ظهور النوع يلعب فقط دور تحسين قابلية تطوير البرنامج من خلال تعدد الأشكال، وليس له أي تأثير آخر. لذلك، لا توجد طرق في التعليمات البرمجية المصدر لواجهة النوع.