GrabDuck

Java. Экспресс-курс: Оператор switch

:

В отличие от операторов if-then и if-then-else, оператор switch применим к известному числу возможных ситуаций. Можно использовать простые типы byte, short, char, int. Также можно использовать Enum и String (начиная с JDK7), и специальные классы, которые являются обёрткой для примитивных типов: Character, Byte, Short, Integer.

Дублирование значений case не допускается. Тип каждого значения должен быть совместим с типом выражения.

Команду switch часто называют командой выбора. Выбор осуществляется в зависимости от целочисленного выражения. Форма команды выглядит так:

switch(ВыражениеДляСравнения) {
    case Совпадение1: 
	    команда;
		break;
	case Совпадение2: 
	    команда;
		break;
	case Совпадение3: 
	    команда;
		break;
	default: 
	    оператор;
	    break;
}

Параметр ВыражениеДляСравнения - выражение, в результате вычисления которого получается целое число (как правило). Команда switch сравнивает результат ВыражениеДляСравнения с каждым последующим Совпадением. Если обнаруживается совпадение, то исполняется команда или набор команд, которые прописаны за данным оператором. Если совпадений не будет, то исполняется команда после ключевого слова default. Однако оператор default не является обязательным. В этом случае при отсутствии совпадений программа не выполняет никаких действий.

Каждая секция case обычно заканчивается командой break, которая передаёт управление к концу команды switch.

Рассмотрим простейший пример с месяцами. Запустим наш учебный проект и добавим код в обработчик нажатия кнопки:


int month = 3;
String monthString;
switch (month) {
    case 1:  monthString = "Январь";
             break;
    case 2:  monthString = "Февраль";
             break;
    case 3:  monthString = "Март";
             break;
    case 4:  monthString = "Апрель";
             break;
    case 5:  monthString = "Май";
             break;
    case 6:  monthString = "Июнь";
             break;
    case 7:  monthString = "Июль";
             break;
    case 8:  monthString = "Август";
             break;
    case 9:  monthString = "Сентябрь";
             break;
    case 10: monthString = "Октябрь";
             break;
    case 11: monthString = "Ноябрь";
             break;
    case 12: monthString = "Декабрь";
             break;
    default: monthString = "Не знаем такого";
             break;
}
mInfoTextView.setText(monthString);

Запустите проект и нажмите кнопку - в текстовом поле появится слово Март (любимый месяц котов).

При желании, можно переписать пример с использованием if-then-else:


int month = 3;
if (month == 1) {
    mInfoTextView.setText("Январь");
} else if (month == 2) {
	mInfoTextView.setText("Февраль");
}
...  // и так далее

В каждом блоке case имеется оператор break, который прерывает свой блок кода. Его нужно использовать обязательно, иначе выполнение кода продолжится. Хотя иногда это и используется.


java.util.ArrayList<String> futureMonths = new java.util.ArrayList<String>();

int month = 8;

switch (month) {
case 1:
	futureMonths.add("January");
case 2:
	futureMonths.add("February");
case 3:
	futureMonths.add("March");
case 4:
	futureMonths.add("April");
case 5:
	futureMonths.add("May");
case 6:
	futureMonths.add("June");
case 7:
	futureMonths.add("July");
case 8:
	futureMonths.add("August");
case 9:
	futureMonths.add("September");
case 10:
	futureMonths.add("October");
case 11:
	futureMonths.add("November");
case 12:
	futureMonths.add("December");
	break;
default:
	break;
}

if (futureMonths.isEmpty()) {
	mInfoTextView.setText("Invalid month number");
} else {
	for (String monthName : futureMonths) {
		mInfoTextView.setText(monthName);
	}
}

Если код в блоках case совпадает, то блоки можно объединить. Например, код для подсчёта дней в месяце:


int month = 2;
int year = 2012;
int numDays = 0;

switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
	numDays = 31;
	break;
case 4:
case 6:
case 9:
case 11:
	numDays = 30;
	break;
case 2:
	if (((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0))
		numDays = 29;
	else
		numDays = 28;
	break;
default:
	mInfoTextView.setText("Несуществующий месяц");
	break;
}
mInfoTextView.setText("Число дней = " + numDays);

При изучении оператора if мы рассматривали пример с временами года. Перепишем его с использованием оператора switch:


int month = 3;
String season;

switch (month) {
case 12:
case 1:
case 2:
	season = "Зимушка-зима";
	break;
case 3:
case 4:
case 5:
	season = "Весна";
	break;
case 6:
case 7:
case 8:
	season = "Лето";
	break;
case 9:
case 10:
case 11:
	season = "Осень";
	break;
default:
	season = "Вы с какой планеты?";
}

mInfoTextView.setText("Мартовские песни коты поют, когда на дворе "
		+ season);

Следующий пример случайным образом генерирует английские буквы. Программа определяет, гласные они или согласные:


Random random = new Random();

for (int i = 0; i < 100; i++) {
	int c = random.nextInt(26) + 'a';
	mInfoTextView.setText((char)c + ", " + c + ": ");
	switch (c) {
	case 'a':
	case 'e':
	case 'i':
	case 'o':
	case 'u':
		mInfoTextView.setText("Гласная");
		break;
	case 'y':
	case 'w':
		mInfoTextView.setText("Условная гласная");
		break;

	default:
		mInfoTextView.setText("Согласная");
		break;
	}
}

Так как метод Random.nextInt(26) генерирует значение между 0 и 26, для получения символа нижнего регистра остаётся прибавить смещение 'a', при этом символ a автоматически преобразуется к типу int. Символы в секциях case также представляют собой целочисленные значения, используемые для сравнения.

Чтобы вывести переменную c в символьном виде, её необходимо преобразовать к типу char, иначе значение будет выведено в числовом виде.

В Java SE 7 появилась возможность использовать объект String в операторе switch. Возможно, это будет работать и на Android в будущем (Upd.: вроде уже работает):


public class StringSwitchDemo {

    public static int getMonthNumber(String month) {

        int monthNumber = 0;

        if (month == null) {
            return monthNumber;
        }

        switch (month.toLowerCase()) {
            case "january":
                monthNumber = 1;
                break;
            case "february":
                monthNumber = 2;
                break;
            case "march":
                monthNumber = 3;
                break;
            case "april":
                monthNumber = 4;
                break;
            case "may":
                monthNumber = 5;
                break;
            case "june":
                monthNumber = 6;
                break;
            case "july":
                monthNumber = 7;
                break;
            case "august":
                monthNumber = 8;
                break;
            case "september":
                monthNumber = 9;
                break;
            case "october":
                monthNumber = 10;
                break;
            case "november":
                monthNumber = 11;
                break;
            case "december":
                monthNumber = 12;
                break;
            default: 
                monthNumber = 0;
                break;
        }

        return monthNumber;
    }

    public static void main(String[] args) {

        String month = "August";

        int returnedMonthNumber =
            StringSwitchDemo.getMonthNumber(month);

        if (returnedMonthNumber == 0) {
            System.out.println("Invalid month");
        } else {
            System.out.println(returnedMonthNumber);
        }
    }
}

Допустимы вложенные операторы switch, но на практике я не сталкивался с таким кодом.

Запомните важные свойства оператора switch:

  • Оператор switch отличается от оператора if тем, что может выполнять проверку только равенства, а оператор if может вычислять результат булева выражения любого типа.
  • Две константы case в одном и том же операторе switch не могут иметь одинаковые значения
  • Оператор switch эффективнее набора вложенных операторов if

Страница документации: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html

Реклама