קריאת הערך של שדות 'פרטיים' ממעמד אחר בג'אווה

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

במדריך מהיר זה נדון כיצד נוכל לגשת לערך של a פְּרָטִי שדה ממעמד אחר בג'אווה.

לפני שמתחילים בהדרכה, עלינו להבין כי פְּרָטִי שינוי הגישה מונע שימוש לרעה בשדות בשוגג. עם זאת, אם אנו רוצים לגשת אליהם, אנו יכולים לעשות זאת באמצעות ה- Reflection API.

2. דוגמא

בואו נגדיר כיתת מדגם אדם עם כמה פְּרָטִי שדות:

אדם ממעמד ציבורי {פרטי שם מחרוזת = "ג'ון"; גיל בתים פרטי = 30; פרטי פרטי uidNumber = 5555; פרטי PIN pin = 452002; איש קשר ארוך פרטי מספר 123456789L; גובה צף פרטי = 6.1242f; משקל כפול פרטי = 75.2564; מין חרבה פרטי = 'M'; פעיל בוליאני פעיל = נכון; // גטרים וקובעים}

3. עשייה פְּרָטִי שדות נגישים

להכין פְּרָטִי נגיש לשטח, עלינו להתקשר ל שדה # set נגיש שיטה:

אדם אדם = אדם חדש (); שדה nameField = person.getClass (). GetDeclaredField ("שם"); nameField.setAccessible (נכון);

בדוגמה שלעיל, תחילה אנו מציינים את השדה אותו אנו רוצים לאחזר - שֵׁם - באמצעות מחלקה # getDeclaredField שיטה. ואז אנו הופכים את השטח לנגיש באמצעות nameField.setAccessible (נכון).

4. גישה פְּרָטִי שדות פרימיטיביים

אנחנו יכולים גישה אל פְּרָטִי שדות שהם פרימיטיביים באמצעות שדה # getXxx שיטות.

4.1. גישה לשדות שלם

אנחנו יכולים להשתמש ב- getByte,getShort, getInt, ו getLong שיטות גישה ל בתים,קצר, int, ו ארוך שדות, בהתאמה:

@ מבחן פומבי בטל כאשר GetIntegerFields_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה ageField = person.getClass (). GetDeclaredField ("גיל"); ageField.setAccessible (נכון); גיל בתים = ageField.getByte (אדם); Assertions.assertEquals (30, גיל); שדה uidNumberField = person.getClass (). GetDeclaredField ("uidNumber"); uidNumberField.setAccessible (נכון); קצר uidNumber = uidNumberField.getShort (אדם); Assertions.assertEquals (5555, uidNumber); שדה pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (נכון); int pinCode = pinCodeField.getInt (אדם); Assertions.assertEquals (452002, pinCode); שדה contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (נכון); contactNumber ארוך = contactNumberField.getLong (אדם); Assertions.assertEquals (123456789L, contactNumber); }

אפשר גם לבצע רישום אוטומטי עם סוגים פרימיטיביים:

@ מבחן ציבורי בטל כאשר DoAutoboxing_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (נכון); מספר שלם pinCode = pinCodeField.getInt (אדם); Assertions.assertEquals (452002, pinCode); }

ה getXxx שיטות לסוגי נתונים פרימיטיביים תומכות גם בהרחבה:

@ מבחן ציבורי בטל כאשרDoWidening_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (נכון); PinCode ארוך = pinCodeField.getLong (אדם); Assertions.assertEquals (452002L, pinCode); }

4.2. גישה לשדות סוג צף

לגשת לָצוּף ו לְהַכפִּיל שדות, עלינו להשתמש ב getFloat ו getDouble שיטות, בהתאמה:

@ מבחן ציבורי בטל כאשר GetFloatingTypeFields_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה heightField = person.getClass (). GetDeclaredField ("גובה"); heightField.setAccessible (נכון); גובה לצוף = heightField.getFloat (אדם); Assertions.assertEquals (6.1242f, גובה); שדה weightField = person.getClass (). GetDeclaredField ("משקל"); weightField.setAccessible (נכון); משקל כפול = weightField.getDouble (אדם); Assertions.assertEquals (75.2564, משקל); }

4.3. גישה לשדות תווים

כדי לגשת ל לְהַשְׁחִיר נוכל להשתמש ב getChar שיטה:

@ מבחן ציבורי בטל כאשר GetCharacterFields_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה genderField = person.getClass (). GetDeclaredField ("מגדר"); genderField.setAccessible (נכון); מגדר char = genderField.getChar (אדם); Assertions.assertEquals ('M', מגדר); }

4.4. גישה לשדות בוליאניים

באופן דומה, אנו יכולים להשתמש ב- getBoolean שיטה לגשת ל בוליאני שדה:

@ מבחן ציבורי בטל כאשר GetBooleanFields_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה activeField = person.getClass (). GetDeclaredField ("פעיל"); activeField.setAccessible (נכון); פעיל בוליאני = activeField.getBoolean (אדם); Assertions.assertTrue (פעיל); }

5. גישה פְּרָטִי שדות שהם אובייקטים

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

@ מבחן פומבי בטל כאשר GetObjectFields_thenSuccess () זורק חריג {אדם אדם = אדם חדש (); שדה nameField = person.getClass (). GetDeclaredField ("שם"); nameField.setAccessible (נכון); שם מחרוזת = (מחרוזת) nameField.get (אדם); Assertions.assertEquals ("ג'ון", שם); }

6. חריגים

עכשיו, בואו נדון בחריגים ש- JVM יכול לזרוק בעת גישה ל- פְּרָטִי שדות.

6.1. IllegalArgumentException

ה- JVM יזרוק IllegalArgumentExceptionאם אנו משתמשים ב- getXxx אביזר שאינו תואם לסוג שדה היעד. בדוגמה שלנו, אם אנחנו כותבים nameField.getInt (אדם), ה- JVM זורק חריג זה מכיוון שהשדה הוא מסוג חוּט ולא int אוֹ מספר שלם:

@ מבט בטל פומבי givenInt_whenSetStringField_thenIllegalArgumentException () זורק חריג {אדם אדם = אדם חדש (); שדה nameField = person.getClass (). GetDeclaredField ("שם"); nameField.setAccessible (נכון); Assertions.assertThrows (IllegalArgumentException.class, () -> nameField.getInt (person)); }

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

@ מבט בטל ציבורי givenInt_whenGetLongField_thenIllegalArgumentException () זורק חריג {אדם אדם = אדם חדש (); שדה contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (נכון); Assertions.assertThrows (IllegalArgumentException.class, () -> contactNumberField.getInt (person)); }

6.2. IllegalAccessException

ה- JVM יזרוק IllegalAccessExceptionאם אנו מנסים לגשת לשדה שאין לו זכויות גישה. בדוגמה שלעיל, אם לא נכתוב את ההצהרה nameField.setAccessible (נכון)ואז ה- JVM משליך את החריג:

@Test ציבורי בטל כאשרFieldNotSetAccessible_thenIllegalAccessException () זורק חריג {אדם אדם = אדם חדש (); שדה nameField = person.getClass (). GetDeclaredField ("שם"); Assertions.assertThrows (IllegalAccessException.class, () -> nameField.get (person)); }

6.3. NoSuchFieldException

אם ננסה לגשת לשדה שאינו קיים בתוך ה אדם בכיתה, אז ה- JVM יכול לזרוק NoSuchFieldException:

Assertions.assertThrows (NoSuchFieldException.class, () -> person.getClass (). GetDeclaredField ("firstName"));

6.4. NullPointerException

לבסוף, כפי שהיית מצפה, ה- JVM זורק א NullPointerExceptionאם נעביר את שם השדה כ- ריק:

Assertions.assertThrows (NullPointerException.class, () -> person.getClass (). GetDeclaredField (null));

7. מסקנה

במדריך זה ראינו כיצד אנו יכולים לגשת ל- פְּרָטִי שדות של כיתה בכיתה אחרת. ראינו גם את החריגים ש- JVM יכול לזרוק ומה גורם להם.

כמו תמיד, הקוד השלם לדוגמא זו זמין ב- GitHub.


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