از Java SE 14 میتوانید نحو راحتتری برای کلیدواژه switch استفاده کنید: عبارت switch (switch expression).
چندین دلیل این نحو جدید را ایجاد کرده است:
case خاص تعریف کنید.case مقداردهی میشود. تبدیل آن به expression (عبارت) کد بهتر و خواناتری ایجاد میکند.نحوی که در بخش قبلی پوشش داده شد، بهعنوان دستور switch شناخته میشود و همچنان در Java SE 14 موجود است و معنای آن تغییر نکرده است. از Java SE 14 نحو جدیدی برای switch در دسترس است: عبارت switch.
این نحو نحو برچسب switch را تغییر میدهد. فرض کنید دستور switch زیر را در برنامه خود دارید:
Day day = Day.MONDAY;
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
}
با نحو عبارت switch، اکنون میتوانید آن را به صورت زیر بنویسید:
Day day = Day.MONDAY;
int len = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
IO.println("len = " + len);
نحو برچسب switch اکنون case L -> است. فقط کدی که در سمت راست برچسب قرار دارد اگر برچسب مطابقت داشته باشد اجرا میشود. این کد میتواند یک عبارت واحد، یک بلوک یا دستور throw باشد. چون این کد یک بلوک واحد است، میتوانید متغیرهایی محلی در آن تعریف کنید.
این نحو همچنین از چندین مقدار ثابت بهازای هر case، جداشده با کاما، پشتیبانی میکند، همانطور که در مثال قبلی نشان داده شد.
دستور switch میتواند بهعنوان عبارت (expression) استفاده شود. به عنوان مثال، مثال بخش قبلی میتواند با دستور switch به صورت زیر بازنویسی شود:
Quarter q = Quarter.Q2;
String season = switch (q) {
case Q4 -> "Q1 - Winter";
case Q1 -> "Q2 - Spring";
case Q2 -> "Q3 - Summer";
case Q3 -> "Q3 - Summer";
default -> "Unknown quarter";
};
اگر فقط یک دستور در بلوک case باشد، مقدار تولیدشده توسط این دستور توسط عبارت switch برگردانده میشود.
در صورت بلوک کد، نحو کمی متفاوت است. بهطور سنتی، کلیدواژه return برای نشان دادن مقدار تولیدشده توسط بلوک کد استفاده میشود. متأسفانه این نحو در مورد دستور switch منجر به ابهام میشود. بیایید مثال زیر را در نظر بگیریم. این کد کامپایل نمیشود، فقط بهعنوان مثال آورده شده است:
String quarterLabel(Quarter q) {
String quarterLabel = switch (q) {
case Q1 -> {
IO.println("Q1 - Winter");
return "Q1 - Winter"; // ← این باعث ابهام است
}
default -> "Unknown quarter";
};
return quarterLabel;
}
بلوک کدی که در حالتی اجرا میشود که quarter برابر ۰ باشد، باید مقداری برگرداند. از کلیدواژه return برای نشان دادن این مقدار استفاده میکند. اگر با دقت به این کد نگاه کنید، دو دستور return میبینید: یکی در بلوک case و دیگری در بلوک متد. اینجا دقیقاً محل ابهام است: ممکن است کسی بپرسد معنای return اول چیست. آیا به این معنی است که برنامه با این مقدار از متد خارج میشود؟ یا از دستور switch خارج میشود؟ چنین ابهاماتی منجر به خوانایی ضعیف و کد مستعد خطا میشود.
نحو جدیدی برای حل این ابهام ایجاد شده است: دستور yield. کد مثال قبلی باید به صورت زیر نوشته شود:
String quarterLabel(Quarter q) {
String quarterLabel = switch (q) {
case Q1 -> {
IO.println("Q1 - Winter");
yield "Q1 - Winter"; // ← yield به جای return
}
default -> "Unknown quarter";
};
return quarterLabel;
}
دستور yield دستوری است که میتواند در هر بلوک case از دستور switch استفاده شود. این دستور با مقداری همراه است که مقدار دستور switch محصورکننده را تشکیل میدهد.
عبارت default به کد شما اجازه میدهد مواردی را مدیریت کنید که مقدار انتخابگر با هیچ مقدار ثابت caseای مطابقت ندارد.
عبارات switch باید جامع (exhaustive) باشند. برای همه مقادیر ممکن، باید برچسب switch مطابقی وجود داشته باشد. دستورات switch الزامی به جامع بودن ندارند. اگر هدف انتخابگر با هیچ برچسب switchای مطابقت نداشته باشد، این دستور switch هیچ کاری نخواهد کرد و ساکت باقی میماند. این میتواند محلی برای مخفی شدن باگها در برنامه شما باشد، چیزی که میخواهید از آن اجتناب کنید.
در بیشتر موارد، جامعیت با استفاده از عبارت default قابل دستیابی است؛ اما در مورد عبارت switch روی enum که همه مقادیر شناختهشده را پوشش میدهد، نیازی به اضافه کردن این عبارت default نیست.
هنوز حالتی وجود دارد که باید با آن برخورد شود. چه اتفاقی میافتد اگر کسی مقدار شمارشی جدیدی به یک enum اضافه کند اما فراموش کند دستورات switch مربوط به آن enum را بهروزرسانی کند؟ برای مدیریت این حالت، کامپایلر عبارت default را برای شما در دستورات switch جامع اضافه میکند. این عبارت default در حالت عادی هیچوقت اجرا نخواهد شد. فقط در صورتی اجرا میشود که مقدار شمارشی جدیدی اضافه شده باشد، و خطای IncompatibleClassChangeError تولید خواهد کرد.
مدیریت جامعیت ویژگیای از عبارات switch است که توسط دستورات switch سنتی ارائه نمیشود و در مواردی غیر از switch روی مقادیر شمارشی (enum) استفاده میشود.
عبارت switch همچنین میتواند از بلوک سنتی case L: استفاده کند. در این حالت، معنای fall through اعمال میشود. مقادیر با استفاده از دستور yield تولید میشوند:
String quarterLabel = switch (q) {
case Q1:
IO.println("Q1 - Winter");
yield "Q1 - Winter";
case Q2:
IO.println("Q2 - Spring");
yield "Q2 - Spring";
case Q3:
IO.println("Q3 - Summer");
yield "Q3 - Summer";
case Q4:
IO.println("Q4 - Fall");
yield "Q4 - Fall";
default:
yield "Unknown quarter";
};
تا اینجا، دستورات switch مقادیر null انتخابگر را نمیپذیرند. اگر سعی کنید روی مقدار null عملیات switch انجام دهید، خطای NullPointerException دریافت خواهید کرد:
String s = null;
int result = switch (s) {
case "Foo" -> 1;
case "Bar" -> 2;
default -> 0;
};
// Throws NullPointerException
Java SE 17 دارای ویژگی پیشنمایشی است که عبارات switch را برای پشتیبانی از مقادیر null بهبود میبخشد، بنابراین میتوانید انتظار داشته باشید این وضعیت تغییر کند.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/