בטל סוג ב- Java

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

כמפתחי Java, אולי נתקלנו ב- בָּטֵל הקלידו באיזה אירוע ותהו מה מטרתו.

במדריך מהיר זה נלמד על הכיתה המוזרה הזו ונראה מתי וכיצד להשתמש בה וכן כיצד להימנע משימוש בה במידת האפשר.

2. מה זה בָּטֵל סוּג

מאז JDK 1.1, Java מספקת לנו את ה- בָּטֵל סוּג. מטרתו היא פשוט לייצג את בָּטֵל סוג החזרה ככיתה ומכיל a מעמד ערך ציבורי. זה לא מיידי, כיוון שהבנאי היחיד שלו הוא פרטי.

לכן, הערך היחיד שנוכל להקצות ל- a בָּטֵל משתנה הוא ריק. זה אולי נראה חסר תועלת מעט, אך כעת נראה מתי ואיך להשתמש בסוג זה.

3. שימושים

ישנם מצבים בעת השימוש ב- בָּטֵל סוג יכול להיות מעניין.

3.1. הִשׁתַקְפוּת

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

בואו נדמיין פשוט מַחשְׁבוֹן מעמד:

מחשבון מחלקה ציבורית {result int int = 0; הוסף ציבורי int (int מספר) {החזרת תוצאה + = מספר; } int int public (int מספר) {return result - = number; } ריק ריק () {result = 0; } הדפסה בטלנית ציבורית () {System.out.println (תוצאה); }}

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

@Test בטל givenCalculator_whenGettingVoidMethodsByReflection_thenOnlyClearAndPrint () {Method [] calculatorMethods = Calculator.class.getDeclaredMethods (); רשימה calculatorVoidMethods = Arrays.stream (calculatorMethods) .filter (שיטה -> method.getReturnType (). שווה (Void.TYPE)) .collect (Collectors.toList ()); assertThat (calculatorVoidMethods) .allMatch (שיטה -> Arrays.asList ("ברור", "הדפס"). מכיל (method.getName ())); }

כפי שאנו יכולים לראות, רק את ברור() ו הדפס() שיטות הוחזרו.

3.2. גנריות

שימוש נוסף של בָּטֵל סוג הוא עם שיעורים גנריים. נניח שאנחנו קוראים לשיטה הדורשת ניתן להתקשר פָּרָמֶטֶר:

מחלקה ציבורית דחייה {דחה V ציבורי סטטי (ניתן להתקשר להתקשרות) זורק חריג {להחזיר להתקשרות.) (); }}

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

@Test בטל givenVoidCallable_whenDiffer_thenReturnNull () זורק חריג {Callable callable = new Callable () {@Override Public Void call () {System.out.println ("Hello!"); החזר אפס; }}; assertThat (Defer.defer (callable)). isNull (); }

יכולנו להשתמש בסוג אקראי (למשל. ניתן להתקשר) ותחזור ריק או בכלל לא סוג (ניתן להתקשר), אבל באמצעות בָּטֵל מציין את כוונותינו בצורה ברורה.

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

דחיית R סטטית ציבורית (פונקציית פונקציה, T arg) {return function.apply (arg); }
@Test בטל givenVoidFunction_whenDiffer_thenReturnNull () {פונקציה פונקציה = s -> {System.out.println ("שלום" + s + "!"); החזר אפס; }; assertThat (Defer.defer (function, "World")). isull (); }

4. כיצד להימנע משימוש בו?

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

כעת נראה כיצד להימנע ממצבים אלה. ראשית, נבחן את השיטה שלנו עם ה- ניתן להתקשר פָּרָמֶטֶר. על מנת להימנע משימוש ב- ניתן להתקשר, אנו עשויים להציע שיטה אחרת לנקוט א ניתן לרוץ פרמטר במקום:

דחיית חלל סטטי ציבורית (Runnable runnable) {runnable.run (); }

אז נוכל להעביר את זה א ניתן לרוץ שלא מחזיר שום ערך וכך נפטר מחסרי התועלת החזר אפס:

Runnable runnable = new Runnable () {@Override public void run () {System.out.println ("שלום!"); }}; לדחות. לדחות (ניתן לרוץ);

אבל אז, מה אם לִדחוֹת הכיתה אינה שלנו לשנות? ואז נוכל להיצמד ל ניתן להתקשר אפשרות או ליצור כיתה אחרת שלוקחת א ניתן לרוץ ודחיית השיחה ל לִדחוֹת מעמד:

מחלקה ציבורית MyOwnDefer {דחיית חלל ציבורית סטטית (Runnable runnable) זורקת Exception {Defer.defer (new Callable () {@Override public Void call () {runnable.run (); return null;}}); }}

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

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

דחיית בטל סטטי ציבורי (צרכן צרכני, ט ארג) {צרכן. קבל (ארג); }

ואז, מה אם הפונקציה שלנו לא לוקחת פרמטר כלשהו? אנו יכולים להשתמש ב- ניתן לרוץ או ליצור ממשק פונקציונאלי משלנו (אם זה נראה ברור יותר):

ממשק ציבורי פעולה {void execute (); }

ואז, אנו מעמיסים יתר על המידה על לִדחוֹת() שיטה שוב:

דחיית חלל סטטי ציבורית (Action action) {action.execute (); }
פעולת פעולה = () -> System.out.println ("שלום!"); לדחות. לדחות (פעולה);

5. מסקנה

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

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