Оператор 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.