التحكّم في التدفّق والحلقات

جملة switch وتعبيرات switch

15 دقيقة الدرس 4 من 14

جملة switch وتعبيرات switch

عندما تحتاج إلى الاختيار بين قيم ثابتة كثيرة، تنجح سلسلة if / else if في المهمة لكنّها تصبح صعبة القراءة سريعًا. تقدّم Java أداة أفضل: جملة switch. تتوفّر في Java نسختان — جملة switch الكلاسيكية الموجودة في اللغة منذ الإصدار الأول، وتعبير switch الحديث الذي أُضيف كميزة رسمية في Java 14. بحلول Java 17 أصبح النموذج الحديث هو الخيار الموصى به في معظم الكود الجديد.

جملة switch الكلاسيكية

يختبر النموذج الكلاسيكي قيمة واحدة مقابل قائمة من تسميات case وينتقل إلى التسمية المطابقة. تمنع جملة break في نهاية كل فرع التنفيذ من الاستمرار إلى الفرع التالي.

int day = 3; String name; switch (day) { case 1: name = "Monday"; break; case 2: name = "Tuesday"; break; case 3: name = "Wednesday"; break; case 4: name = "Thursday"; break; case 5: name = "Friday"; break; default: name = "Weekend"; break; } System.out.println(name); // Wednesday

تسمية default اختيارية لكنّها موصى بها بشدّة — فهي تتعامل مع أي قيمة لا تطابق أيًّا من حالات case، تمامًا كالـ else الأخيرة في سلسلة if.

السقوط التلقائي (Fall-through): ميزة أم خطأ؟

إذا حذفت break، يستمر التنفيذ سقوطًا إلى الحالة التالية ولا يتوقف حتى يصل إلى break أو نهاية الـ switch. هذا السلوك مقصود عند تجميع الحالات التي تشترك في نفس المنطق.

int month = 4; // أبريل int daysInMonth; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: daysInMonth = 31; break; case 4: case 6: case 9: case 11: daysInMonth = 30; break; case 2: daysInMonth = 28; // بدون أخذ السنة الكبيسة بالاعتبار break; default: daysInMonth = -1; } System.out.println(daysInMonth); // 30

هنا تسقط الأشهر 4 و6 و9 و11 إلى نفس إسناد daysInMonth = 30. هذا نظيف ومقصود. أمّا السقوط غير المقصود — نسيان break — فهو من أكثر الأخطاء شيوعًا لدى المبتدئين.

نسيان break خطأ صامت. لا تُحذّرك Java إذا نسيت break. يُجمَّع الكود بنجاح، لكنّ التنفيذ يستمر إلى الحالة التالية وقد يُسند قيمة خاطئة أو يطبع نتيجة غير متوقعة. تحقّق دائمًا من كل فرع في جملة switch الكلاسيكية.

ما الذي يصلح في switch؟

يجب أن تكون قيمة switch أحد الأنواع التالية. لا يمكنك استخدام double أو long أو كائن مخصص.

  • byte وshort وchar وint (وأصناف التغليف المقابلة)
  • String
  • قيم enum

تعبير switch الحديث (Java 14 فأعلى)

يحلّ تعبير switch ثلاث مشكلات في الجملة الكلاسيكية: لا سقوط تلقائي عرضي، ويمكن إسناد النتيجة مباشرةً إلى متغيّر، والصياغة أقصر بكثير. يستخدم كل فرع -> بدلًا من : ولا يسقط تلقائيًا.

int day = 3; String name = switch (day) { case 1 -> "Monday"; case 2 -> "Tuesday"; case 3 -> "Wednesday"; case 4 -> "Thursday"; case 5 -> "Friday"; default -> "Weekend"; }; System.out.println(name); // Wednesday

لاحظ أنّ الـ switch بأكمله تعبير — ينتج قيمة تُخزَّن في name. تأتي الفاصلة المنقوطة في نهاية جملة الإسناد، وليس داخل الفروع.

فضّل تعبيرات switch في الكود الجديد. إنّها أأمن (لا سقوط تلقائي)، وأقصر، ويمكن استخدامها مباشرةً داخل تعبيرات أخرى — مثلًا كوسيطة لاستدعاء دالة أو كقيمة مُعادة.

تجميع الحالات في تعبير switch

يمكنك سرد قيم متعددة في فرع سهم واحد بالفصل بينها بفواصل:

String season = switch (month) { case 12, 1, 2 -> "Winter"; case 3, 4, 5 -> "Spring"; case 6, 7, 8 -> "Summer"; case 9, 10, 11 -> "Autumn"; default -> "Unknown"; };

يحلّ هذا محلّ الحالات الفارغة ذات السقوط في النموذج الكلاسيكي بسطر واحد مقروء.

فروع متعددة الأسطر مع yield

عندما يحتاج فرع إلى أكثر من تعبير واحد — مثل حساب متغيّر محلي — ضع الجسم بين أقواس معقوفة واستخدم yield لإعادة القيمة:

int score = 85; String grade = switch (score / 10) { case 10, 9 -> "A"; case 8 -> "B"; case 7 -> "C"; case 6 -> { System.out.println("Just passed!"); yield "D"; } default -> { System.out.println("Failed."); yield "F"; } }; System.out.println(grade); // B

تُستخدم yield فقط داخل فرع كتلة في تعبير switch. إنّها تختلف عن return — فهي تخرج من كتلة الـ switch، لا من الدالة بأكملها.

مقارنة سريعة: جملة switch مقابل تعبير switch

  • الجملة الكلاسيكية — تستخدم case X:، تتطلّب break، السقوط التلقائي ممكن، لا تنتج قيمة.
  • التعبير الحديث — يستخدم case X ->، لا سقوط تلقائي، ينتج قيمة، ويستخدم yield للكتل متعددة الأسطر.
الاستيفاء الشامل. عند استخدام تعبير switch مع enum، يتحقّق مُجمِّع Java من أنّ كل قيمة ممكنة مغطّاة. إذا فاتتك واحدة تحصل على خطأ أثناء التجميع — وهذا أفضل بكثير من عطل وقت التشغيل.

الخلاصة

جملة switch الكلاسيكية مفيدة لكنّها تتطلّب إدارة دقيقة لـ break والتعامل المتعمّد مع السقوط التلقائي. تعبير switch الحديث، المتاح من Java 14 فصاعدًا، يُلغي السقوط العرضي، ويتيح الإسناد المباشر، ويُبقي الكود موجزًا. بالنسبة لكود Java 17 الذي تكتبه في هذه الدورة، فضّل نموذج التعبير بالسهم افتراضيًا، والجأ إلى الجملة الكلاسيكية فقط عندما تحتاج صراحةً إلى سلوك السقوط التلقائي.