מתי ג'אווה זורקת UndeclaredThrowableException?

ג'אווה טופ

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

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

במדריך זה, נראה מה גורם לג'אווה לזרוק מופע של UndeclaredThrowableException יוצא מן הכלל.

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

2. ה UndeclaredThrowableException

באופן תיאורטי, ג'אווה תשליך מופע של UndeclaredThrowableException כאשר אנו מנסים לזרוק חריג מסומן שאינו מוכרז. כלומר, לא הכרזנו על החריג המסומן ב זורק סעיף אך אנו זורקים את החריג הזה בגוף השיטה.

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

חלל ציבורי לא מוכרז () {לזרוק IOException חדש (); }

מהדר Java נכשל עם ההודעה:

java: חריג לא מדווח java.io.IOException; חייבים להיתפס או להכריז שהם נזרקים

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

שמירת חלל ציבורי (נתוני אובייקט) {// הושמט}

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

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

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

3. Proxy דינמי של Java

כדוגמא הראשונה שלנו, בואו ליצור proxy זמן ריצה עבור java.util.List ממשק ומיירט את שיחות השיטה שלו. ראשית, עלינו ליישם את InvocationHandler ממשק ושם את ההיגיון הנוסף שם:

מחלקה ציבורית ExceptionalInvocationHandler מיישם את InvocationHandler {@Override Public Object invoke (Proxy Object, Method method, Object [] args) throws Throwable {if ("size" .equals (method.getName ())) {throw new SomeCheckedException ("Always fail") ); } זרק RuntimeException חדש (); }} מחלקה ציבורית SomeCheckedException מרחיב חריג {public SomeCheckedException (הודעת מחרוזת) {super (הודעה); }}

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

בואו נראה כיצד ג'אווה מטפלת בשני המצבים. ראשית, נקרא List.size () שיטה:

ClassLoader classLoader = getClass (). GetClassLoader (); InvocationHandler invocationHandler = חדש ExceptionalInvocationHandler (); רשימת proxy = (רשימה) Proxy.newProxyInstance (classLoader, מחלקה חדשה [] {List.class}, invocationHandler); assertThatThrownBy (proxy :: size) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeCheckedException.class);

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

אם אנו קוראים לכל שיטה אחרת ב- רשימה מִמְשָׁק:

assertThatThrownBy (proxy :: isEmpty) .isInstanceOf (RuntimeException.class);

מכיוון שה- proxy משליך חריג לא מסומן, Java מאפשרת לחריג להפיץ כפי שהוא.

4. היבט אביב

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

@Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) ציבורי @interface ThrowUndeclared {}

כעת אנו ממליצים לייעץ לכל השיטות המוערות בהערה זו:

@Aspect @ Component public class UndeclaredAspect {@Around ("@ annotation (undeclared)") public Object advis (ProceedingJoinPoint pjp, ThrowUndeclared undeclared) זורק זורק {זרוק חדש SomeCheckedException ("AOP בדוק חריג"); }}

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

@Service מחלקה ציבורית UndeclaredService {@ThrowUndeclarly public void doSomething () {}}

אם נקרא לשיטה המאושרת, ג'אווה תשליך מופע של UndeclaredThrowableException יוצא מן הכלל:

@RunWith (SpringRunner.class) @SpringBootTest (class = UndeclaredApplication.class) מחלקה ציבורית UndeclaredThrowableExceptionIntegrationTest {@Autowired שירות UndeclaredService פרטי; @Test הציבור בטל givenAnAspect_whenCallingAdvisedMethod_thenShouldWrapTheException () {assertThatThrownBy (service :: doSomething) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeCheckedException.class). }}

כפי שמוצג לעיל, Java מקפלת את החריג בפועל כסיבה וזורקת את UndeclaredThrowableException במקום זאת חריג.

5. מסקנה

במדריך זה ראינו מה גורם לג'אווה לזרוק מופע של ה- UndeclaredThrowableException יוצא מן הכלל.

כרגיל, כל הדוגמאות זמינות ב- GitHub.

תחתית Java

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

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