JavaRush /مدونة جافا /Random-AR /بيان التبديل في جافا

بيان التبديل في جافا

نشرت في المجموعة
تخيل أنك تقف عند مفترق الطرق، مثل بطل من لوحة شهيرة. إذا اتجهت إلى اليسار ستفقد جوادك، وإذا اتجهت إلى اليمين ستكتسب المعرفة. كيفية برمجة مثل هذا الوضع؟ من المرجح أنك تعلم بالفعل أننا نتخذ مثل هذا الاختيار باستخدام بنيات if-then و if-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
ماذا لو لم يكن هناك مساران من هذا القبيل، بل 10؟ هل هناك طريق "إلى اليمين"، "قليلاً إلى اليسار"، "إلى اليسار قليلاً" وما إلى ذلك، بمبلغ 10 قطع؟ تخيل كيف سينمو كود if-then-else الخاص بك في هذا الإصدار!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
إذن، ليس لديك شوكة واحدة من الشروط، بل عدة، على سبيل المثال، 10 (الشيء المهم هنا هو أن عدد الشوكات محدود). في مثل هذه المواقف، يوجد عامل اختيار خاص - حالة التبديل java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
أمر التنفيذ في البيان هو كما يلي:
  • يتم تقييم SelectionExpression. بعد ذلك، تقوم عبارة التبديل بمقارنة التعبير الناتج بالقيمة التالية (بالترتيب المذكور).
  • إذا كان SelectExpression يطابق القيمة، فسيتم تنفيذ الكود الذي يلي النقطتين.
  • إذا تمت مواجهة بناء الاستراحة ، فسيتم نقل التحكم خارج أمر التبديل.
  • إذا لم يتم العثور على تطابقات بين ExpressionForSelection والقيم، فسيتم نقل التحكم إلى DefaultSelectionCode.
نقاط مهمة
  • يجب أن يكون نوع SelectionExpression لبيان تحديد التبديل في Java واحدًا مما يلي:

    • بايت , قصير , شار , كثافة العمليات .
    • أغلفةها هي Byte ، Short ، Character ، Integer .
    • سلسلة (منذ جافا 7).
    • التعداد ( التعداد ).
  • الكتلة الافتراضية اختيارية، فإذا لم يتطابق SelectionExpression والقيم، فلن يتم تنفيذ أي إجراء.
  • الفاصل اختياري؛ إذا لم يكن موجودًا، فسيستمر تنفيذ التعليمات البرمجية (تجاهل المزيد من مقارنات القيم في كتل الحالة) حتى breakمواجهة بيان التبديل الأول أو حتى النهاية.
  • إذا كان من الضروري تنفيذ نفس الكود لعدة خيارات تحديد، لتجنب الازدواجية، نشير إلى عدة قيم مقابلة أمامه في كتل حالة متتالية .

دعنا ننتقل إلى ممارسة استخدام عبارة التبديل في 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 ماذا يحدث إذا قمنا بإزالة جميع عبارات 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.

الاختلافات من إذا

نظرًا للتشابه الخارجي بين عبارات if و switch ، لا تنس أن مفتاح تشغيل الاختيار المتعدد يبني اختيار خيارات التنفيذ على قيمة محددة، بينما في if. يمكن أن يكون أي تعبير منطقي. خذ هذه الحقيقة في الاعتبار عند تصميم التعليمات البرمجية الخاصة بك. دعونا نلقي نظرة فاحصة على ابتكارات التبديل في إصدارات مختلفة من Java.

التبديل في جافا 7

قبل Java 7، كان من الممكن استخدام العناصر الأولية byte وshort وchar وint كقيمة للمحول. كان هناك أيضًا دعم للتعداد والمغلفات من الأنواع البدائية المذكورة أعلاه: الحرف والبايت والقصير والعدد الصحيح. ولكن غالبًا ما نحتاج إلى العثور على قيمة سلسلة تبديل 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 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 !");
}
على الرغم من الميزات الجديدة، فإن أسلوب استخدام التعداد أكثر مرونة ويوصى باستخدامه: يمكننا إعادة استخدام هذا التعداد عدة مرات.

التبديل في جافا 12

قام Java 12 بتحسين تعبيرات التبديل لمطابقة الأنماط. إذا استخدمنا 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. إذا قمنا سابقًا بتعيين قيمة متغيرة داخل كتل الحالة، نظرًا لأن عبارة التبديل نفسها لا يمكنها إرجاع أي شيء، فلدينا الآن مثل هذه الفرصة، ونقوم بإرجاع القيمة مباشرة باستخدام التبديل.

  2. في السابق، لم يعد بإمكاننا الحصول على أي شيء على يمين الفاصل، لكننا الآن نستخدمه كبيان إرجاع لإرجاع قيمة رمز التبديل الخاص بنا. تشير علامات النقطتين إلى نقطة الإدخال في كتلة البيان. أي أنه من تلك النقطة يبدأ تنفيذ جميع التعليمات البرمجية أدناه، حتى عند مواجهة تسمية أخرى.

    والنتيجة هي انتقال شامل من علامة إلى أخرى، وهو ما يسمى أيضًا بالسقوط .

بيان التبديل في جافا - 2لإكمال مثل هذا التمرير، يجب عليك إما المرور عبر جميع العناصر بالكامل، أو استخدام الفاصل أو العودة. يمنحنا الابتكار في Java 12 القدرة على استخدام عامل التشغيل lambda، والذي بدوره يضمن تنفيذ التعليمات البرمجية الموجودة على يمينه فقط. دون أي "فشل". كيف سيكون شكل المثال السابق في هذه الحالة:
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;
};

التبديل في جافا 13

في Java 13، تغيرت الطريقة التي يُرجع بها المحول قيمة. إذا كتبنا في جافا 12 القيمة المرتجعة بعد الفاصل، والتي كانت بمثابة عائد لنا لكتلة التبديل، فسنقوم الآن بإرجاع القيمة باستخدام الكلمة عائد . دعونا ننظر:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
في الوقت نفسه، لن يتم تجميع التعليمات البرمجية المكتوبة في Java 12 باستخدام Break للعودة (( بيان التبديل في جافا - 3سيتم استخدام Break، ولكن في المواقف التي لا نحتاج فيها إلى إرجاع أي شيء.

المجموع

  • استخدم بيان الحالة عندما يكون هناك أكثر من فرعين لتجنب ازدحام التعليمات البرمجية الخاصة بك مع بنيات if.
  • لا تنس إنهاء الكتلة المنطقية لكل فرع المقابلة لقيمة محددة (كتلة الحالة) باستدعاء فاصل .
  • بالإضافة إلى بعض الأنواع البدائية، يمكن لتعليمة التبديل أيضًا استخدام أنواع Enum و String كتعبيرات .
  • تذكر الكتلة الافتراضية - استخدمها للتعامل مع قيم التحديد غير المخطط لها.
  • لتحسين الأداء، انقل فروع التعليمات البرمجية ذات الاختيارات الأكثر شيوعًا إلى بداية كتلة التبديل.
  • لا تنجرف في "التحسين" عن طريق إزالة الفاصل الموجود في نهاية كتلة تحديد الحالة - فمن الصعب فهم مثل هذا الكود، ونتيجة لذلك، يصعب الحفاظ عليه أثناء تطويره.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION