Оператор switch case в Java улучшает читаемость кода. Но он имеет ряд ограничений и особенностей, о которых стоит знать — мы их рассмотрим.
Пример использования switch
Оператором switch можно заменить вот такой длинный вложенный if:
if (day.equals("MON") || day.equals("TUE") || day.equals("WED") || day.equals("THU")) { return "Time to work"; } else if (day.equals("FRI")) { return "Nearing weekend"; } else if (day.equals("SAT") || day.equals("SUN")) { return "Weekend!"; } else { return "Invalid day?"; }
Тот же самый код со switch:
switch (day) { case "MON": case "TUE": case "WED": case "THU": result = "Time to work"; break; case "FRI": result = "Nearing weekend"; break; case "SAT": case "SUN": result = "Weekend!"; break; default: result = "Invalid day?"; }
Согласитесь, что со switch код выглядит гораздо понятнее:
- Если день недели равен понедельник, вторник, среда или четверг, то результат равен «Time to work«
- Если пятница, то «Nearing weekend«
- Если суббота или воскресенье, то «Weekend!«
- Блок в default выполняется, если никакие значения, заданные в операторах case, не подходят. В этом случае возвращается «Invalid day?».
Блок default не обязатален, оператор switch корректен и без него - break означает выйти из switch
Теперь о странностях. Не забывайте ставить операторы break. Несмотря на то, что в 95% кода логика построена так, что надо покинуть switch после выполнения ровно одного блока, break надо писать вручную, иначе будут выполняться нижележащие блоки.
Операторы break
Если забыть поставить операторы break в предыдущем примере, то результат будет странным — Invalid day?.
Давайте проверим. Изменим предыдущий пример, добавив вывод в консоль и сделав String day = «MON»:
public String forgetBreak() { String day = "MON"; String result; switch (day) { case "MON": case "TUE": case "WED": case "THU": System.out.println("Time to work"); result = "Time to work"; case "FRI": System.out.println("Nearing weekend"); result = "Nearing weekend"; case "SAT": case "SUN": System.out.println("Weekend!"); result = "Weekend!"; default: System.out.println("Invalid day?"); result = "Invalid day?"; } return result; }
Если бы во всех блоках стояли операторы break, то результат был бы равен Time to work, и это было бы правильно.
Но без оператора break мы заходим во все нижележащие case и default (пока не встретится break), в итоге мы выполняем все блоки, и результат будет равен «Invalid day?» Посмотрите на вывод в консоль, по выводу видно, что мы проходим все блоки:
Time to work Nearing weekend Weekend! Invalid day?
Требования к аргументу switch
switch применим далеко не ко всем типам данных, а только к четырем примитивам и их оберткам, а также String (начиная с Java 7) и enum:
- char, Character
- byte, Byte
- short, Short
- int, Integer
- Character
- String
- enum
double и float исключены, потому что в Java сравнивать значения этих типов нельзя без указания точности.
Невозможно сравнить в switch и объекты всех других типов — ни по ссылке, ни с помощью equal().
Мы столкнемся с этим исключением, если напишем в вышеприведенном примере:
String day =null;
Сравнение строк
Стоит отметить, что строки сравниваются с помощью equal(), то есть если создать строку с помощью new:
String day = new String("MON");
а потом сравнить ее в операторе switch со значением «MON»:
public String compareStringObject() { String day = new String("MON"); String result; switch (day) { case "MON": case "TUE": case "WED": case "THU": result = "Time to work"; break; case "FRI": result = "Nearing weekend"; break; case "SAT": case "SUN": result = "Weekend!"; break; default: result = "Invalid day?"; break; } return result; }
то строки будут равны. То есть result = «Time to work»
Требования к значениям в case
Значения в case тоже не могут быть равны null, иначе код не скомпилируется.
Кроме того, в case должны быть именно значения (либо переменные final). Например, такой код скомпилируется только в том случае, если перед переменной m стоит final:
public String caseNotFinal() { String day = new String("MON"); final String m= "MON"; String result; switch (day) { case m: case "TUE": case "WED": case "THU": result = "Time to work"; break; case "FRI": result = "Nearing weekend"; break; case "SAT": case "SUN": result = "Weekend!"; break; default: result = "Invalid day?"; break; } return result; }
Еще все значения должны быть одного типа, то есть нельзя в аргумент switch передавать, например, переменную типа int, а в case — значение типа double.
Итог
Мы рассмотрели тонкости оператора switch. Код примеров доступен на GitHub.