Оператор switch

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

Аргумент switch не должен быть равен null, иначе в процессе выполнения  возникнет NullPointerException.

Мы столкнемся с этим исключением, если напишем в вышеприведенном примере:

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.

 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *