בודק אם קיימת כיתה בג'אווה

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

בדיקת קיומו של מחלקה יכולה להיות שימושית בבואנו לקבוע באיזה יישום ממשק להשתמש. טכניקה זו משמשת בדרך כלל במהלך הגדרות JDBC ישנות יותר.

במדריך זה, נחקור את הניואנסים של השימוש Class.forName () כדי לבדוק את קיומו של מחלקה במסלול ג'אווה.

2. שימוש Class.forName ()

אנו יכולים לבדוק את קיומו של מחלקה באמצעות Java Reflection, באופן ספציפי Class.forName (). מהתיעוד עולה כי א ClassNotFoundException ייזרק אם לא ניתן לאתר את הכיתה.

2.1. מתי לצפות ClassNotFoundException

ראשית, בואו נכתוב מבחן שבוודאי יזרוק א ClassNotFoundException כדי שנוכל לדעת שהבדיקות החיוביות שלנו בטוחות:

@Test (צפוי = ClassNotFoundException.class) חלל ציבורי givenNonExistingClass_whenUsingForName_thenClassNotFound () זורק ClassNotFoundException {Class.forName ("class.that.does.not.exist"); }

אז הוכחנו שכיתה שלא קיימת תזרוק א ClassNotFoundException. בואו לכתוב מבחן לשיעור שאכן קיים:

@Test הציבור בטל שניתןExistingClass_whenUsingForName_thenNoException () זורק ClassNotFoundException {Class.forName ("java.lang.String"); }

בדיקות אלה מוכיחות זאת רץ Class.forName () ולא תופס א ClassNotFoundException שווה ערך למחלקה שצוינה הקיימת במסלול הכיתה. עם זאת, זה לא ממש פתרון מושלם בגלל תופעות לוואי.

2.2. תופעת לוואי: אתחול כיתתי

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

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

מחלקה סטטית ציבורית InitializingClass {static {if (true) {// מאפשרים השלכה של חריג בבלוק אתחול סטטי, זורק RuntimeException חדש); }}}

אנו יכולים לראות מה forName () תיעוד שהוא זורק ExceptionInInitializerError אם האתחול שעוררה בשיטה זו נכשל.

בוא נכתוב מבחן שצפוי ל- ExceptionInInitializerError כשמנסים למצוא את שלנו InitializingClass מבלי לציין מטעין כיתות:

@Test (צפוי = ExceptionInInitializerError.class) חלל ציבורי givenInitializingClass_whenUsingForName_thenInitializationError () זורק ClassNotFoundException {Class.forName ("path.to.InitializingClass"); }

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

3. מספרים Class.forName () לדלג על אתחול

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

על פי התיעוד, השיחות הבאות שוות ערך:

Class.forName ("Foo") Class.forName ("Foo", נכון, this.getClass (). GetClassLoader ())

על ידי שינוי נָכוֹן ל שֶׁקֶר, כעת נוכל לכתוב מבחן הבודק את קיומו של שלנו InitializingClassמבלי להפעיל את חסימת האתחול הסטטית שלו:

@Test הציבור בטל givenInitializingClass_whenUsingForNameWithoutInitialization_thenNoException () זורק ClassNotFoundException {Class.forName ("path.to.InitializingClass", false, getClass (). GetClassLoader ()); }

4. Java 9 מודולים

עבור פרויקטים של Java 9+, יש עומס יתר שלישי על Class.forName (), שמקבל א מודול ו חוּט שם הכיתה. עומס יתר זה אינו מפעיל את אתחול המחלקה כברירת מחדל. כמו כן, בעיקר, הוא חוזר ריק כאשר הכיתה המבוקשת אינה קיימת במקום לזרוק א ClassNotFoundException.

5. מסקנה

במדריך קצר זה, חשפנו את תופעת הלוואי של אתחול הכיתה בעת השימוש Class.forName () ומצאתי שאתה יכול להשתמש ב- forName () עומסי יתר כדי למנוע את זה.

קוד המקור עם כל הדוגמאות במדריך זה ניתן למצוא באתר GitHub.


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