מדריך לכלי עזר להשתקפות של גויאבה

1. סקירה כללית

במאמר זה נבחן את ה- גויאבההִשׁתַקְפוּת API - שהוא בהחלט תכליתי יותר בהשוואה ל- API של השתקפות Java רגיל.

נשתמש גויאבה כדי לתפוס סוגים גנריים בזמן הריצה, ואנחנו נשתמש בזה טוב בלתי ניתן לרישום גם כן.

2. לכידת סוג גנרי בזמן זמן ריצה

בג'אווה מיושמים גנריות עם מחיקת סוגים. פירוש הדבר שמידע הסוג הגנרי זמין רק בזמן הקומפילציה ובזמן הריצה הוא כבר לא זמין.

לדוגמה, רשימה, המידע על סוג גנרי נמחק בזמן הריצה. בשל עובדה זו, אין זה בטוח להעביר סביב הגנריות מעמד חפצים בזמן ריצה.

בסופו של דבר נקצה שתי רשימות בעלות סוגים גנריים שונים לאותה התייחסות, וזה ללא ספק לא רעיון טוב:

List stringList = Lists.newArrayList (); רשימת intList = Lists.newArrayList (); תוצאה בוליאנית = stringList.getClass () .isAssignableFrom (intList.getClass ()); assertTrue (תוצאה);

בגלל מחיקת סוגים, השיטה isAssignableFrom () לא יכול לדעת את הסוג הגנרי בפועל של הרשימות. זה בעצם משווה בין שני סוגים שהם רק א רשימה ללא כל מידע אודות הסוג בפועל.

באמצעות ממשק ה- API של השתקפות Java אנו יכולים לזהות את סוגי השיטות והמחלקות הגנריות. אם יש לנו שיטה שמחזירה א רשימהנוכל להשתמש בבבואה כדי להשיג את סוג ההחזרה של אותה שיטה - א ParameterizedType מייצג רשימה.

ה TypeToken class משתמש בפתרון זה כדי לאפשר מניפולציה של סוגים גנריים. אנחנו יכולים להשתמש ב- TypeToken בכיתה כדי ללכוד סוג בפועל של רשימה גנרית ולבדוק אם באמת ניתן להתייחס אליהם באותה התייחסות:

TypeToken stringListToken = קוד סוג חדש() {}; TypeToken integerListToken = קוד סוג חדש() {}; TypeToken numberTypeToken = TypeToken חדש() {}; assertFalse (stringListToken.isSubtypeOf (integerListToken)); assertFalse (numberTypeToken.isSubtypeOf (integerListToken)); assertTrue (integerListToken.isSubtypeOf (numberTypeToken));

רק ה integerListToken ניתן להקצות להפניה מסוג nubmerTypeToken כי an מספר שלם הכיתה מרחיבה א מספר מעמד.

3. לכידת סוגים מורכבים באמצעות TypeToken

בואו נגיד שאנחנו רוצים ליצור מחלקה פרמטרית כללית ואנחנו רוצים לקבל מידע על סוג כללי בזמן הריצה. אנחנו יכולים ליצור כיתה שיש לה TypeToken כשדה ללכידת מידע זה:

מחלקה מופשטת ParametrizedClass {TypeToken type = TypeToken new (getClass ()) {}; }

ואז, בעת יצירת מופע מאותו מחלקה, הסוג הגנרי יהיה זמין בזמן הריצה:

ParametrizedClass parametrizedClass = ParametrizedClass חדש () {}; assertEquals (parametrizedClass.type, TypeToken.of (String.class));

אנחנו יכולים גם ליצור TypeToken מסוג מורכב שיש בו יותר מסוג כללי אחד, ואחזר מידע על כל אחד מאותם סוגים בזמן הריצה:

TypeToken funToken = TypeToken חדש() {}; TypeToken funResultToken = funToken .resolveType (Function.class.getTypeParameters () [1]); assertEquals (funResultToken, TypeToken.of (String.class));

אנו מקבלים סוג החזר בפועל עבור פוּנקצִיָה, זה חוּט. אנו יכולים אפילו לקבל סוג של ערך במפה:

TypeToken mapToken = TypeToken חדש() {}; TypeToken entrySetToken = mapToken .resolveType (Map.class.getMethod ("entrySet") .getGenericReturnType ()); assertEquals (entrySetToken, TypeToken חדש<>>() {}); 

כאן אנו משתמשים בשיטת השתקפות getMethod () מספריית Java הסטנדרטית כדי ללכוד את סוג ההחזרה של שיטה.

4. בלתי ניתן לרישום

ה בלתי ניתן לרישום הוא עטיפה שוטפת של java.lang.reflect.Method ו java.lang.reflect.Constructor. הוא מספק ממשק API פשוט יותר על גבי ג'אווה רגילה הִשׁתַקְפוּת ממשק API. בואו נגיד שיש לנו כיתה שיש לה שתי שיטות ציבוריות ואחת מהן היא סופית:

class CustomClass {public void somePublicMethod () {} public final void notOverridablePublicMethod () {}}

עכשיו בואו נבחן את somePublicMethod () באמצעות API של גויאבה ותקן Java הִשׁתַקְפוּת ממשק API:

שיטת שיטה = CustomClass.class.getMethod ("somePublicMethod"); בלתי ניתנים להזמנה = TypeToken חדש () {} .שיטה (שיטה); isPublicStandradJava בוליאני = Modifier.isPublic (method.getModifiers ()); isPublicGuava בוליאני = invokable.isPublic (); assertTrue (isPublicStandradJava); assertTrue (isPublicGuava);

אין הבדל גדול בין שתי הגרסאות הללו, אך לבדוק אם שיטה ניתנת לניתוח יתר היא משימה ממש לא טריוויאלית בג'אווה. למרבה המזל, ה isOverridable () שיטה מה- בלתי ניתן לרישום הכיתה מקלה על:

שיטת שיטה = CustomClass.class.getMethod ("notOverridablePublicMethod"); בלתי ניתנת להזמנה ללא הזמנה = TypeToken חדש () {} .שיטה (שיטה); בוליאני isOverridableStandardJava = (! (Modifier.isFinal (method.getModifiers ()) || Modifier.isPrivate (method.getModifiers ()) || Modifier.isStatic (method.getModifiers ()) || Modifier.isFinal (method.getDeclaringClass ( ) .getModifiers ()))); בוליאני isOverridableFinalGauava = invokable.isOverridable (); assertFalse (isOverridableStandardJava); assertFalse (isOverridableFinalGauava);

אנו רואים שגם פעולה כה פשוטה מצריכה הרבה בדיקות באמצעות תקן הִשׁתַקְפוּת ממשק API. ה בלתי ניתן לרישום class מסתיר זאת מאחורי ה- API הפשוט לשימוש ותמציתי ביותר.

5. מסקנה

במאמר זה בחנו את ממשק ה- API של השתקפות גויאבה והשווינו אותו לג'אווה הרגילה. ראינו כיצד לתפוס סוגים כלליים בזמן ריצה, וכיצד בלתי ניתן לרישום class מספק API אלגנטי וקל לשימוש עבור קוד המשתמש בבבואה.

ניתן למצוא את היישום של כל הדוגמאות וקטעי הקוד בפרויקט GitHub - זהו פרויקט Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.


$config[zx-auto] not found$config[zx-overlay] not found