Рубрики
Без рубрики

Выражение переключения (JEP 361)

Java имеет оператор switch от самого первого кандидата на выпуск. Существующая реализация Switch follow… Помеченный как java, производительность.

Java имеет оператор switch от самого первого кандидата на выпуск. Существующая реализация Switch соответствует дизайну и синтаксису процедурных языков (C и C++) и по умолчанию поддерживает сквозную семантику.

Типичная реализация switch выглядит следующим образом:

private static int existingSwitchWithDefault(DAY day){
    int numberOfCharacters = 0;
    switch(day){
        case MONDAY:
        case FRIDAY:
            numberOfCharacters = 6;
            break;
        case TUESDAY:
            numberOfCharacters = 7;
            break;
        case WEDNESDAY:
            numberOfCharacters = 9;
            break;
        case THURSDAY:
        case Saturday:
            numberOfCharacters = 8;
            break;
        default:
            throw new IllegalArgumentException("Invalid input "+day+" provided.");
    }
    return  numberOfCharacters;
}

Некоторая проблема с существующим оператором switch:

  • Дефолт проваливается

Как и в других процедурных языках, переход по умолчанию поддерживается оператором switch. Это обоюдоострый меч, иногда полезный, но часто опасный и неприятное место для жука, чтобы спрятаться.

В приведенном выше примере, если разработчик пропустит, чтобы поставить **разбейте * * и напишите такой код

private static int existingSwitchWithBug(DAY day){
    int numberOfCharacters = 0;
    switch(day){
        case WEDNESDAY:
            numberOfCharacters = 9; // Missed a break FALL THROUGH
        case THURSDAY:
            numberOfCharacters = 8;
            break;
    }
    return  numberOfCharacters;
}   

и метод будет вызываться как ” ** существующий коммутатор с ошибкой (ДЕНЬ.СРЕДА)” * * он вернет 8, а не 9, из-за провала. Такого рода ошибки нелегко обнаружить без надлежащего модульного тестирования.

  • значение по умолчанию не

Наличие регистра по умолчанию не является обязательным в существующем операторе switch, если разработчик вызывает указанный выше метод, например ” **existingSwitchWithBug(DAY.MONDAY) * *” он просто вернет 0. Это может быть допустимым бизнес-примером, но в большинстве случаев это происходит из-за того, что разработчик забывает охватить все необходимые случаи в инструкции switch.

Разве это не приятно, если компилятор делает обязательным наличие регистра по умолчанию в инструкции switch?

  • Слишком многословно

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

Что такое выражение переключателя?

Выражение переключения было выпущено в качестве функции предварительного просмотра в JDK 12 с JEP 325 (в этом приложении **перерыв* * был перегружен для возврата результата из выражения switch) на основе отзывов сообщества (разработчик считает, что использование break для возврата из выражения switch сбивает с толку), был введен новый JEP 325 (новый оператор yield, введенный для возврата и восстановивший первоначальное значение break), который реализован и выпущен как функция предварительного просмотра с JDK 13.

Выражение переключения выпущено в качестве стандартной функции с JDK 14.

Прежде чем двигаться дальше, важно понять разницу между утверждением и выражением. Выражение вычисляет значение (вы можете распечатать его или присвоить переменной), а оператор что-то делает, представляет действие или команду (if else или циклы)

Если вы помните пример инструкции switch, упомянутый выше, то же самое можно записать с помощью выражения switch, как показано ниже:

private static int withSwitchExpression(String day){
    int result = switch (day){
        case "Monday","Friday" -> 6;
        case "Tuesday" ->7;
        case "Wednesday" ->9;
        case "Thursday" ->8;
        default -> throw new IllegalStateException("Unexpected value: " + day);
    };
    return result;
}

Несколько вещей, которые следует отметить в приведенном выше фрагменте:

  • Новая форма метки переключателя, “регистр L ->” , чтобы указать, что только код справа от метки должен выполняться, если метка соответствует. Код справа от “case L ->” может быть только выражением, блоком или оператором throw.
  • Если метка сопоставлена, то выполняется только выражение или оператор справа от стрелки; провала нет.
  • Операторы Switch расширены, поэтому их можно использовать как выражение, пожалуйста, помните о разнице, упомянутой выше, между оператором и выражением.
  • В случае выражения switch требуется регистр по умолчанию, чтобы подчеркнуть, что рассматриваются все возможные случаи, регистр по умолчанию может быть пропущен, если вы используете Enum в качестве идентификатора случая, компилятор может видеть, охвачены ли все случаи или нет

Приведенный ниже код в полном порядке, не будет никаких ошибок во время компиляции

switch(day){
    case MONDAY,FRIDAY,SUNDAY -> 6;
    case TUESDAY -> 7;
    case WEDNESDAY -> 9;
    case THURSDAY,SATURDAY -> 8;
};

уступать

До сих пор мы видели пример, в котором регистр выражения switch содержит только одну строку кода, как насчет того, если вам нужно написать блок примерно так, как показано ниже:

private static int switchWithBlock(String day){
    int numOfDays = switch (day){
        case "Monday","Friday" -> 6;
        case "Tuesday" ->7;
        case "Wednesday" ->9;
        case "Thursday" ->8;
        default ->{
            int len = day.length();
            yield len;
        }
    };
    return numOfDays;
}

и если вы вызываете вышеупомянутый метод с кодом типа ” ** switch With Block(“bizzare”) * *”, метод вернет 7 из регистра по умолчанию. Здесь вы должны обратить внимание на yield, он представляет собой оператор для получения значения.

Оператор switch, но не выражение switch, может быть целью оператора break. И наоборот, выражение switch, но не оператор switch, может быть целью оператора yield.

### Область действия локальной переменной

В инструкции switch, если вы объявите локальную переменную в регистре, она также будет доступна для других регистров (видимость локальной переменной также работает только как сквозная), см. Приведенный ниже код

switch (day){
    case MONDAY:
        int expense = 50;
        System.out.println("Monday expense is " + 50);
        break;
    case TUESDAY: {
        expense = 90;
        break;
    }
}

здесь переменная ” расход ” доступна для случая ВТОРНИКА и даже была объявлена в случае ПОНЕДЕЛЬНИКА.

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

switch (day){
    case MONDAY: {
        int expense = 50;
        System.out.println("Monday expense is " + expense);
        break;
    }
    case TUESDAY: {
        int expense = 90;
        System.out.println("Tuesday expense is " +expense);
        break;
    }
}

здесь переменная “расход” объявлена и используется только в конкретном случае.

Давайте теперь посмотрим, как локальная переменная работает с выражением switch, см. Фрагмент ниже:

switch (day){
    case MONDAY ->{
        int expense = 50;
        System.out.println("Monday expense is "+expense);
    }
    case TUESDAY ->{
        int expense = 60;
        System.out.println("Monday expense is "+expense);
    }
}   

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

Примечание: – Как оператор switch, так и выражение switch являются допустимыми параметрами для JDK 14 и более поздних версий.

Оригинал: “https://dev.to/imagarg/switch-expression-jep-361-1onk”