مثل الجملة الشرطية if/else، تتيح لك عبارة switch تغيير مسار البرنامج عبر تنفيذ الكود تنفيذًا شرطيًا.
الفرق أن عبارة switch لا تستطيع إلا مقارنة قيمة تعبير من نوع أوّلي أو تعبير نصّي بقيم ثابتة معرّفة مسبقًا.
هناك بعض الكلمات المفتاحية المفيدة عند استخدام عبارة switch.
switch: تتيح لك هذه الكلمة المفتاحية تعريف بنية switch.
ويأتي بعدها التعبير أو المتغير الذي سيغيّر النتيجة.case: ستستخدمها لتعريف الاحتمالات المختلفة للنتيجة.break: الكلمة المفتاحية break مفيدة جدًا لإيقاف تنفيذ switch عند نهاية المسار المطلوب.
وإذا نسيتها، فسيستمر البرنامج وقد يؤدي ذلك إلى نتائج غير متوقعة.default: كما يوحي اسمها، استخدمها كنتيجة افتراضية عندما لا تطابق أي case أخرى نتيجة تعبيرك.في أبسط صورها، تختبر عبارة switch تعبيرًا من نوع أوّلي أو تعبيرًا نصيًا وتتخذ قرارًا بناءً على قيمته.
على سبيل المثال:
String direction = getDirection();
switch (direction) {
case "left":
goLeft();
break;
case "right":
goRight();
break;
default:
// otherwise
markTime();
break;
}
بدءًا من Java 14 (وكانت متاحة كمعاينة سابقة في Java 12 و13)، أصبح من الممكن استخدام التنفيذ "المُحسَّن" لـ switch.
يمكنك إسناد قيم متعددة إلى case واحدة.
في عبارة switch التقليدية يمكنك أن تدع التنفيذ ينتقل إلى الحالة التالية. في المثال التالي ستُنفّذ case 1 وcase 3 الشيء نفسه.
ويحدث ذلك لأن case 1 لا تستخدم الكلمة المفتاحية break.
switch (number) {
case 1:
case 3:
// do same stuff
break;
case 2:
// do different stuff
break;
// (...)
}
وفي switch expression المُحسَّنة يمكنك إسناد قيم متعددة مباشرةً إلى case واحدة.
انظر إلى المثال التالي:
switch (number) {
case 1, 3:
// do stuff
break;
case 2:
// do other stuff
break;
// (...)
}
يمكنك الآن كتابة switch-statement أو switch expression.
فما الفرق؟
ببساطة، العبارة تتطلب منطقًا صارمًا، بينما يمكن للتعبير أن يُرجع قيمة.
فبدلًا من:
String result = "";
switch (expression) {
case "bob":
result = "bob";
break;
// (...)
}
يمكنك أن تكتب:
String result = switch (expression) {
case "bob":
yield "bob";
// (...)
}
تعمل yield مثل return لكنها مخصّصة لتعبير switch.
ولأن yield تنهي التعبير، فلا حاجة إلى break هنا.
فرق آخر بين عبارات switch و_تعبيرات switch_: في تعبيرات switch يجب أن تغطي جميع الحالات.
إما بأن يكون لديك case لكل القيم الممكنة أو باستخدام حالة default.
يمكنك استخدام -> بدلًا من :.
ويتيح لك -> عدم تضمين الكلمة المفتاحية break.
يمكن استخدام كلتا الصيغتين، لكن عليك في switch واحدة أن تلتزم بواحدة فقط.
switch(expression) {
case 1 -> yield "one"
case 2 -> yield "two"
default: yield "other number" // Removing this will result in a compile error
}
النطاق.
قد تؤدي switch التقليدية إلى سلوك غير متوقع بسبب نطاقها، إذ يوجد نطاق واحد فقط لكامل switch.
switch(expression) {
case 1:
String message = "something";
break;
case 2:
String message = "anything";
break;
// (...)
}
هذا المثال لا يعمل لأن message معرّف مرتين داخل switch.
ويمكن حلّ ذلك باستخدام:
switch (expression) {
case 1: {
String message = "something";
break;
}
case 2: {
String message = "anything";
break;
}
// (...)
}
إذ إن {} تحدّد نطاق case.
لكن هذا ليس بديهيًا لأن {} ليست إلزامية.
ومع ذلك، إذا استخدمت صيغة -> الجديدة، فيجب أن يتبعها أحد الأمور: عبارة/تعبير واحد، أو عبارة throw، أو كتلة {}.
لا مزيد من الالتباس!
يمكنك العثور على مزيد من المعلومات حول switch المُحسَّنة في هذا المقال وهذا الآخر، إلى جانب توثيق Oracle الرسمي.
بالإضافة إلى ذلك، أُضيفت في Java 21 ميزة تُسمّى Guarded Patterns، وتتيح لك إجراء فحوصات داخل تسمية case نفسها.
String dayOfMonth = getDayOfMonth();
String day = "";
return switch (day) {
case "Tuesday" when dayOfMonth == 13 -> "Forbidden day!!";
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "Week day";
case "Saturday", "Sunday" -> "Weekend";
default -> "Unknown";
};
يمكنك العثور على مزيد من المعلومات حول تعبير switch في Java 21 في هذه المدونة