JavaRush /בלוג Java /Random-HE /החלף משפט ב-Java

החלף משפט ב-Java

פורסם בקבוצה
דמיינו שאתם עומדים על מזלג, כמו גיבור מציור מפורסם. אם תלך שמאלה, תאבד את הסוס שלך; אם תלך ימינה, תרכוש ידע. איך לתכנת מצב כזה? סביר להניח שאתה כבר יודע שאנחנו מבצעים בחירה כזו באמצעות המבנים אם-אז ואם -אז-אחר .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
מה אם אין שני מסלולים כאלה, אלא 10? האם יש שביל "ימינה", "קצת שמאלה", "קצת יותר שמאלה" וכן הלאה, בכמות של 10 חתיכות? תאר לעצמך איך הקוד אם-אז-אחר שלך יגדל בגרסה זו!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
אז, אין לך מזלג אחד של תנאים, אלא כמה, למשל, 10 (הדבר החשוב כאן הוא שמספר המזלגות מוגבל). עבור מצבים כאלה, יש אופרטור בחירה מיוחד - switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
צו הביצוע בהצהרה הוא כדלקמן:
  • ה- SelectionExpression מוערך. לאחר מכן, הצהרת switch משווה את הביטוי המתקבל עם הערך הבא (בסדר הרשום).
  • אם ה- SelectExpression תואם ל- Value, אזי הקוד שאחרי הנקודתיים מבוצע.
  • אם נתקלים במבנה ההפסקה , השליטה מועברת מחוץ לפקודת המתג.
  • אם לא נמצאו התאמות בין ExpressionForSelection ל-Values, השליטה מועברת ל-DefaultSelectionCode.
נקודות חשובות
  • סוג SelectionExpression עבור הצהרת בחירת מתג ב-Java חייב להיות אחד מהבאים:

    • byte , short , char , int .
    • העטיפות שלהם הן בייט , קצר , תו , מספר שלם .
    • מחרוזת (מאז Java 7).
    • ספירה ( Enum ).
  • בלוק ברירת המחדל הוא אופציונלי, ואז אם ה- SelectionExpression והערכים אינם תואמים, לא תבוצע פעולה.
  • break הוא אופציונלי; אם הוא לא קיים, הקוד ימשיך לפעול (התעלמות מהשוואות נוספות של ערכים בבלוקים של מקרה) עד breakלהיתקל בהצהרת הבורר הראשונה או עד הסוף.
  • אם יש צורך להפעיל את אותו קוד עבור מספר אפשרויות בחירה, כדי למנוע כפילות אנו מציינים לפניו מספר ערכים תואמים בבלוקים עוקבים .

בואו נעבור לתרגול השימוש במשפט ה-switch ב-Java

אל דאגה, סיימנו עם התיאוריה, ואחרי דוגמאות נוספות הכל יתברר הרבה יותר. אז בואו נתחיל. בואו נסתכל על דוגמה מהאסטרונומיה על כוכבי הלכת של מערכת השמש. בהתאם לתקנות הבינלאומיות העדכניות ביותר, אנו לא נכלול את פלוטו (בשל תכונות המסלול שלו). הבה נזכור שכוכבי הלכת שלנו ממוקמים מהשמש ברצף הבא: מרקורי, נוגה, כדור הארץ, מאדים, צדק, שבתאי, אורנוס ונפטון. בואו ניצור שיטת Java שמקבלת כקלט את המספר הסידורי של כוכב הלכת (ביחס למרחק מהשמש), וכפלט מייצרת את ההרכב העיקרי של האטמוספירה של כוכב הלכת הזה בצורה של רשימה <String> . הרשו לי להזכיר לכם שלכמה כוכבי לכת יש הרכב אטמוספירה דומה. לפיכך, נוגה ומאדים מכילים בעיקר פחמן דו חמצני, צדק ושבתאי מורכבים ממימן והליום, ובאורנוס ונפטון, בנוסף לצמד הגזים האחרון, יש גם מתאן. הפונקציה שלנו:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
שימו לב: השווינו את אותו קוד לכוכבי לכת בעלי הרכב אטמוספרי זהה. ועשינו זאת על ידי שימוש בקונסטרוקציות רציפות של מקרה . לכן, אם אנחנו רוצים לקבל את הרכב האטמוספירה של כוכב הלכת הביתי שלנו, אנחנו קוראים לשיטה שלנו עם פרמטר 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
ניסוי עם break מה קורה אם נסיר את כל הצהרות הפסקה ? בואו ננסה את זה בפועל:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
אם נדפיס את התוצאה של השיטה System.out.println(getPlanetAtmosphere(3)), אז כוכב הבית שלנו לא יתאים כל כך לחיים. או מתאים? תשפטו בעצמכם: [פחמן דו חמצני, חנקן, חמצן, מימן, הליום, מתאן, מימן, הליום], למה זה קרה? התוכנית ביצעה את כל המקרים לאחר ההתאמה הראשונה ועד סוף בלוק המתגים.

הפסקת אופטימיזציה מוגזמת

שימו לב שאנחנו יכולים לשפר את השיטה עם סידור שונה של הנחיות הפסקה ואפשרויות בחירה
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
נראה קצר יותר, לא? צמצמנו את המספר הכולל של ההצהרות על ידי משחק בסדר תיק וקיבוץ מחדש. כעת כל סוג גז מתווסף לרשימה בשורת קוד אחת בלבד. רישום הדוגמה האחרונה של השיטה מוצג רק כדי להדגים את העבודה, מאוד לא מומלץ לכתוב בסגנון כזה. אם המחבר (ועוד יותר מתכנתי צד שלישי) של קוד דומה צריך לתחזק אותו, אז יהיה קשה מאוד לשחזר את ההיגיון להיווצרות בלוקי בחירה וקוד הפעלה עבור הצהרת ה-java switch.

הבדלים מאם

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

החלף ב-Java 7

לפני Java 7, ניתן היה להשתמש בפרימיטיבים של byte, short, char ו-int כערך למתג. הייתה גם תמיכה ב-enum ובעטיפות מהסוגים הפרימיטיביים המפורטים לעיל: Character, Byte, Short ו-Integer. אבל לעתים קרובות אנחנו צריכים למצוא את הערך של מחרוזת מתג Java! כך זה ייראה ב-Java 6:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
ומנו:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
אבל החל מ-Java 7, אפשר היה להשתמש בסוג String כערך עבור מתג:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
למרות התכונות החדשות, הגישה באמצעות enum גמישה יותר ומומלצת לשימוש: אנו יכולים לעשות שימוש חוזר ב-enum זה פעמים רבות.

החלף ב-Java 12

Java 12 שיפר את ביטויי Switch עבור התאמת דפוסים. אם נשתמש ב-Switch כמו בדוגמה למעלה, כדי להגדיר את הערך של משתנה כלשהו, ​​היינו צריכים לחשב את הערך ולהקצות אותו למשתנה הנתון, ולאחר מכן להשתמש ב-break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
אבל הודות ליכולות של Java 12, אנו יכולים לשכתב את הביטוי הזה באופן הבא:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
בואו נעבור קצת על השינויים:
  1. אם בעבר קבענו ערך משתנה בתוך בלוקים של מקרה, מכיוון שהצהרת ה-switch עצמה לא יכלה להחזיר דבר, כעת יש לנו הזדמנות כזו, ואנו מחזירים ישירות את הערך באמצעות ה-switch.

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

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

הצהרת החלף ב-Java - 2כדי להשלים מעבר כזה, עליך לעבור את כל האלמנטים במלואם, או להשתמש בהפסקה או חזרה. החידוש ב-java 12 נותן לנו את היכולת להשתמש באופרטור למבדה, שבתורו מבטיח שרק הקוד מימין לו יבוצע. בלי שום "כשל". איך תיראה הדוגמה הקודמת במקרה זה:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
הקוד הפך להרבה יותר פשוט, לא? ועוד משהו: אופרטור הלמבדה יכול לשמש גם כאנלוג אופייני למעי הגס, שאחריו יש בלוק שלם עם כמה פעולות:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
ובכן, מה אם במקרים מסוימים ערך ההחזר זהה? מסתבר שלמעשה יש לנו אותם מקרים לכמה ערכים שונים. כך ניתן לקצר זאת באמצעות תכונות חדשות ב-Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

החלף ב-Java 13

ב-Java 13, הדרך שבה מתג מחזיר ערך השתנתה. אם ב-java 12 כתבנו את ערך ההחזרה לאחר הפסקה, ששימש עבורנו תמורה לבלוק המתג, כעת נחזיר את הערך באמצעות המילה תשואה . בואו נראה:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
יחד עם זאת, קוד שנכתב ב-java 12 באמצעות break to return לא יתבצע קומפילציה (( הצהרת החלף ב-Java - 3ייעשה שימוש ב-Break, אבל במצבים בהם לא נצטרך להחזיר דבר.

סה"כ

  • השתמש בהצהרת המקרה כאשר יש יותר משני ענפים כדי למנוע עמוס בקוד שלך במבני if.
  • אל תשכח לסיים את הבלוק הלוגי של כל סניף המתאים לערך מסוים (בלוק מקרה) עם קריאת הפסקה .
  • בנוסף לכמה טיפוסים פרימיטיביים, משפט ה-switch יכול להשתמש גם בסוגי Enum ו- String כביטויים .
  • זכור את בלוק ברירת המחדל - השתמש בו כדי לטפל בערכי בחירה לא מתוכננים.
  • כדי לייעל את הביצועים, העבר את ענפי הקוד עם האפשרויות הנפוצות ביותר לתחילת בלוק המתגים.
  • אל תיסחף עם "אופטימיזציה" על ידי הסרת ההפסקה בסוף בלוק בחירת המקרה - קוד כזה קשה להבנה, וכתוצאה מכך קשה לתחזק אותו במהלך הפיתוח שלו.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION