Заявление о переключении Java

Заявление о переключении Java

1. обзор

В этом руководстве мы узнаем, что такое операторswitch и как его использовать.

Операторswitch позволяет нам заменить несколько вложенных конструкцийif-else и, таким образом, улучшить читаемость нашего кода.

Switch со временем эволюционировал - были добавлены новые поддерживаемые типы, особенно в Java 5 и 7. Кроме того, он продолжает развиваться - выраженияswitch, вероятно, будут введены в Java 12.

Ниже мы приведем несколько примеров кода, чтобы продемонстрировать использование оператораswitch, роль оператораbreak, требования к значениям аргументаswitch /case и сравнениеStrings в выраженииa switch.

Перейдем к примеру.

2. Пример использования

Допустим, у нас есть следующие вложенные операторыif-else:

public String exampleOfIF(String animal) {
    String result;
    if (animal.equals("DOG") || animal.equals("CAT")) {
        result = "domestic animal";
    } else if (animal.equals("TIGER")) {
        result = "wild animal";
    } else {
        result = "unknown animal";
    }
    return result;
}

Приведенный выше код выглядит некрасиво, его сложно поддерживать и рассуждать. Чтобы улучшить читаемость, мы могли бы использовать здесь операторswitch:

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
            result = "domestic animal";
            break;
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

Как показано выше, мы сравниваем аргументswitchanimal с несколькими значениямиcase. Если ни одно из значенийcase не равно аргументу, то выполняется блок под меткойdefault.

Проще говоря, операторbreak используется для выхода из оператораswitch.

3. Заявлениеbreak

Хотя большинство операторовswitch в реальной жизни подразумевают, что должен быть выполнен только один из блоковcase, операторthe break необходим для выхода изswitch после завершения блока.

Если мы забудем написатьbreak, будут выполнены следующие блоки.

Чтобы продемонстрировать это, давайте опустим операторыbreak и добавим вывод в консоль для каждого блока:

public String forgetBreakInSwitch(String animal) {
    switch (animal) {
    case "DOG":
        System.out.println("domestic animal");
    default:
        System.out.println("unknown animal");
    }
}

Давайте выполним этот кодforgetBreakInSwitch (“DOG”), и проверим вывод, чтобы убедиться, что все блоки выполняются:

domestic animal
unknown animal

Поэтому нам следует быть осторожными и добавлять операторыbreak в конце каждого блока, если нет необходимости переходить к коду под следующей меткой.

Единственный блок, гдеbreak не нужен, - это последний, но добавлениеbreak к последнему блоку делает код менее подверженным ошибкам.

Мы также можем воспользоваться этим поведением дляomit break when we want the same code executed for several case statements.. Давайте перепишем пример из предыдущего раздела, сгруппировав вместе первые 2 случая:

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

4. Аргументswitch и значенияcase

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

4.1. Типы данных

Мы не можем сравнивать все типы объектов и примитивов в оператореswitch. A switch works only with four primitives and their wrappers, as well as with the enum type and the String class:

  • byte иByte

  • short иShort

  • int иInteger

  • char иCharacter

  • enum

  • строка

СтильString доступен в оператореswitch, начиная с Java 7.

Типenum был представлен в Java 5 и с тех пор доступен в оператореswitch.

Классы Wrapper также доступны с Java 5.

Конечно, аргументswitch и значенияcase должны быть одного типа.

4.2. No null Valuesс

We can’t pass the null value as an argument to a switch statement. Если мы это сделаем, программа выдастNullPointerException,, используя нашу первую половинкуswitch :

@Test(expected=NullPointerException.class)
public void whenSwitchAgumentIsNull_thenNullPointerException() {
    String animal = null;
    Assert.assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

Конечно, мы также не можем передатьnull в качестве значения меткеcase оператораswitch. Если мы сделаем это, код не скомпилируется.

4.3. ЗначенияCase как константы времени компиляции

Если мы попытаемся заменить значение caseDOG на переменнуюdog , код не будет компилироваться, пока мы не отметим переменнуюdog какfinal:

final String dog="DOG";
String cat="CAT";

switch (animal) {
case dog: //compiles
    result = "domestic animal";
case cat: //does not compile
    result = "feline"
}

4.4. String Сравнение

Если в оператореswitch используется оператор равенства для сравнения строк, мы не сможем правильно сравнить аргументString, созданный с помощью оператораnew, со значением caseString.

К счастью,switch operator uses the equals() method under the hood.

Продемонстрируем это:

@Test
public void whenCompareStrings_thenByEqual() {
    String animal = new String("DOG");
    assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

5. Новое выражениеswitch

ДоступенJava 12, а вместе с ним и предварительный просмотр новой функции - менее подробное выражениеswitch.

Чтобы включить его, нам нужно передать компилятору–enable-preview.

Давайте взглянем:

var month = JUN;
var value = switch(month) {
  case JAN, JUN, JUL -> 3;
  case FEB, SEP, OCT, NOV, DEC -> 1;
  case MAR, MAY, APR, AUG -> 2;
};

System.out.println(value); // 3

Чтобы использовать новый синтаксис, мы больше не используем двоеточие, а оператор, известный из Lambda Expressions. Обратите внимание на отсутствие ключевого словаbreak и отсутствие провалов.

Но все еще есть возможность получить детальный контроль над тем, что происходит в правой части выражения, с помощью блоков кода. В таком случае нам нужно вручную извлечь из негоbreak и указать возвращаемое значение:

public static void switchLocalVariable() {
    var month = Month.AUG;
    int i = switch (month){
        case JAN,JUN, JUL -> 3;
        case FEB,SEP, OCT, NOV, DEC -> 1;
        case MAR,MAY, APR, AUG -> {
            int j = month.toString().length() * 4;
            break j;
        }
    };
    System.out.println(i); //12
}

6. Заключение

В этом руководстве мы узнали о тонкостях использования оператораswitch в Java. Мы можем решить, использовать лиswitch , исходя из удобочитаемости и типа сравниваемых значений.

Оператор switch является хорошим кандидатом для случаев, когда у нас есть ограниченное количество опций в предопределенном наборе (например, дни недели). В противном случае нам придется изменять код каждый раз, когда добавляется или удаляется новое значение, что может оказаться невозможным. В этих случаях мы должны рассмотреть другие подходы, такие какpolymorphism или другие шаблоны проектирования, такие какCommand.

Как всегда доступен полный кодover on GitHub.