JavaRush /בלוג Java /Random-HE /הפסקת קפה מס' 161. כיצד לטפל ב-Null ב-Java באמצעות אופציו...

הפסקת קפה מס' 161. כיצד לטפל ב-Null ב-Java באמצעות אופציונלי

פורסם בקבוצה
מקור: בינוני מאמר זה יעזור לך להבין טוב יותר את המטרה של אופציונלי בעת עבודה עם קוד Java. הפסקת קפה מס' 161.  כיצד לטפל ב-Null ב-Java באמצעות אופציונלי - 1כשהתחלתי לעבוד עם קוד Java, לעתים קרובות המליצו לי להשתמש באופציונלי. אבל בזמנו לא הבנתי מעט מדוע השימוש באופציונלי היה טוב יותר מאשר הטמעת טיפול עבור ערכי null. במאמר זה, אני רוצה לשתף אתכם מדוע אני חושב שכולנו צריכים להשתמש יותר באופציונלי, וכיצד להימנע מאופציונליות יתר של הקוד שלכם, דבר שמזיק לאיכות הקוד.

מה זה אופציונלי?

הפרמטר האופציונלי משמש לשאת אובייקטים ולאפשר טיפול בהפניות Null על ידי ממשקי API שונים. בואו נסתכל על קטע הקוד:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
יש לנו מופע קפה שבו אנו מקבלים כמות מסוימת של סוכר ממופע של אובייקט הסוכר . אם נניח שערך הכמות מעולם לא הוגדר בבנאי Coffee , אז coffee.getSugar().getQuantity() יחזיר NullPointerException . כמובן שתמיד נוכל להשתמש בבדיקות null ישנות וטובות כדי לתקן את הבעיה.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
עכשיו נראה שהכל בסדר. אבל כשכותבים קוד Java, מוטב שנמנע מיישום בדיקות null . בואו נראה כיצד ניתן לעשות זאת באמצעות אופציונלי.

כיצד ליצור אופציונלי

ישנן שלוש דרכים ליצור אובייקטים אופציונליים:
  • of(ערך T) - מופע של אובייקט אופציונלי שאינו ריק. שים לב ששימוש ב-() כדי להתייחס לאובייקט null יזרוק NullPointerException .

  • ofNullable(T value) - יוצר ערך אופציונלי עבור אובייקט שיכול להיות null.

  • empty() - יוצר מופע אופציונלי המייצג הפניה ל- null .

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
אז יש לך אובייקט אופציונלי. עכשיו בואו נסתכל על שתי השיטות העיקריות עבור אופציונלי:
  • isPresent() - שיטה זו אומרת לך אם האובייקט האופציונלי מכיל ערך שאינו ריק.

  • get() - מאחזר את הערך עבור Optional עם הערך הנוכחי. שים לב שקריאה get() על אופציונלי ריק תגרום ל- NullPointerException .

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

שיפור בדיקת Null עם אופציונלי

אז איך נוכל לשפר את הקוד לעיל? עם Optional נוכל להבין את נוכחותו של אובייקט באמצעות isPresent() ולאחזר אותו באמצעות get() . נתחיל מאריזת התוצאה של coffee.getSugar() עם Optional ובאמצעות שיטת isPresent() . זה יעזור לנו לקבוע אם getSugar() מחזירה null.
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
בהסתכלות על דוגמה זו, אריזה של התוצאה של coffee.getSugar() ב-Optional לא נראה כתוספת ערך, אלא מוסיפה טרחה. נוכל לשפר את התוצאה על ידי שימוש במה שאני מחשיב כפונקציות האהובות עלי מהמחלקה האופציונלית:
  • map(Function<? super T,? extends U> maper) - ממפה את הערך הכלול באופציונלי לפונקציה המסופקת. אם הפרמטר Optional ריק, אז map() יחזיר את Optional.empty() .

  • orElse(T other) היא גרסה "מיוחדת" של שיטת get() . זה יכול לקבל את הערך הכלול ב-Optional. עם זאת, במקרה של אופציונלי ריק, זה יחזיר את הערך שהועבר לשיטת orElse() .

השיטה תחזיר את הערך הכלול במופע האופציונלי. אבל אם הפרמטר Optional ריק, כלומר אינו מכיל ערך, אז orElse() יחזיר את הערך המועבר לחתימת השיטה שלו, הידועה כערך ברירת המחדל.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
זה ממש מגניב - לפחות אני חושב שכן. עכשיו, אם במקרה של ערך ריק אנחנו לא רוצים להחזיר את ערך ברירת המחדל, אז אנחנו צריכים לזרוק איזשהו חריג. orElseThrow(Supplier<? extends X> exceptionSupplier) מחזיר את הערך הכלול בפרמטרים אופציונליים, או זורק חריג אם האופציונלי ריק.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
כפי שאתה יכול לראות, אופציונלי מספק מספר יתרונות:
  • תקציר בדיקות null
  • מספק API לטיפול באובייקטים null
  • מאפשר לגישה ההצהרתית לבטא את מה שהושג

כיצד להפוך לאפקטיבי עם אופציונלי

בעבודה שלי, אני משתמש באופציונלי כסוג החזרה כאשר שיטה יכולה להחזיר מצב "אין תוצאה". אני בדרך כלל משתמש בו כשמגדיר סוגי החזרות לשיטות.
Optional<Coffee> findByName(String name) {
   ...
}
לפעמים זה לא הכרחי. לדוגמה, אם יש לי שיטה שמחזירה int , כמו getQuantity() במחלקה Sugar , אז השיטה עשויה להחזיר 0 אם התוצאה היא null כדי לייצג "no quantity". כעת, בידיעה זו, אנו יכולים לחשוב שניתן לייצג את פרמטר הסוכר במחלקת קפה כאופציונלי. במבט ראשון, זה נראה כמו רעיון טוב שכן, בתיאוריה, סוכר לא צריך להיות נוכח בקפה. עם זאת, זה המקום שבו אני רוצה להתייחס מתי לא להשתמש באופציונלי. עלינו להימנע משימוש באופציונלי בתרחישים הבאים:
  • כסוגי פרמטרים עבור POJOs , כגון DTOs . אופציות אינן ניתנות לסידרה, כך שהשימוש בהן ב-POJO משבית את יכולת הסידרה של האובייקט.

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

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

סיכום

אופציונלי הפך לתוספת רבת עוצמה לספריית Java. זה מספק דרך לטפל באובייקטים שאולי לא קיימים. לכן, יש לקחת זאת בחשבון בעת ​​פיתוח שיטות מבלי ליפול למלכודת של התעללות. כן, אתה יכול לכתוב קוד מעולה שמיישם בדיקות null וטיפול null, אבל קהילת Java מעדיפה להשתמש ב-Optional. הוא מתקשר ביעילות כיצד לטפל בערכים חסרים, קל הרבה יותר לקריאה מאשר בדיקות Nul מבולגנות, ומביא פחות באגים בקוד שלך בטווח הארוך.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION