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

Как часть Java SE 12, switchвыражения были введены, а начиная с Java SE 14 они были стандартизированы. Чем они отличаются от операторов switch?


person Arvind Kumar Avinash    schedule 10.01.2021    source источник
comment
Что означает стандартизированный по сравнению с введенным?   -  person rogerdpack    schedule 26.01.2021
comment
@rogerdpack Это должно относиться к выражениям переключения, представленным в качестве функции предварительного просмотра в JDK 12 - полностью пригодной для использования и полной, включенной с помощью параметров компилятора, по-прежнему допускающей (нарушающие) изменения в будущих версиях на основе отзывов пользователей. В JDK 14 это было объединено в качестве стандартной функции, которая больше не изменится в будущих версиях.   -  person tryman    schedule 27.01.2021


Ответы (3)


Оператор switch:

В отличие от оператора if/else if/else, оператор switch может иметь несколько возможных путей выполнения. switch работает с примитивными типами byte, short, char и int, их соответствующими типами-оболочками (Byte, Short, Character и Integer), перечисляемыми типами и типом String1. В то время как оператор if-else используется для проверки выражений, основанных на диапазонах значений или условий, оператор switch используется для проверки выражений, основанных только на одном значении.

Демо

enum PaymentStatus {
    UNPAID, PARTPAID, PAID, DISPUTED, UNKNOWN;
}

public class Main {
    public static void main(String[] args) {
        String message = "";
        PaymentStatus paymentStatus = PaymentStatus.PARTPAID;

        switch (paymentStatus) {
        case UNPAID:
            message = "The order has not been paid yet. Please make the minimum/full amount to procced.";
            break;
        case PARTPAID:
            message = "The order is partially paid. Some features will not be available. Please check the brochure for details.";
            break;
        case PAID:
            message = "The order is fully paid. Please choose the desired items from the menu.";
            break;
        default:
            throw new IllegalStateException("Invalid payment status: " + paymentStatus);
        }
        System.out.println(message);
    }
}

Вывод:

The order is partially paid. Some features will not be available. Please check the brochure for details.

Выражение switch:

Выражение switch было введено в Java SE 12. Однако оно оставалось в качестве функции Preview в Java SE 12 и 13 и, наконец, было стандартизировано в Java SE 14. Как и любое выражение, switch выражений дают одно значение и могут использоваться в операторах. Он также представил метки со стрелками case, устраняющие необходимость в операторах break для предотвращения провала. Начиная с Java SE 15, поддерживаемые типы данных не изменились (упомянутые в разделе операторов switch выше).

Демо

enum PaymentStatus {
    UNPAID, PARTPAID, PAID, DISPUTED, UNKNOWN;
}

public class Main {
    public static void main(String[] args) {
        PaymentStatus paymentStatus = PaymentStatus.PARTPAID;

        String message = switch (paymentStatus) {
        case UNPAID -> "The order has not been paid yet. Please make the minimum/full amount to procced.";
        case PARTPAID -> "The order is partially paid. Some features will not be available. Please check the brochure for details.";
        case PAID -> "The order is fully paid. Please choose the desired items from the menu.";
        default -> throw new IllegalStateException("Invalid payment status: " + paymentStatus);
        };

        System.out.println(message);
    }
}

Вывод:

The order is partially paid. Some features will not be available. Please check the brochure for details.

Выражение switch с yield:

Начиная с Java SE 13, вы можете использовать оператор yield вместо оператора стрелки (-›), чтобы вернуть значение из выражения switch.

Демо

enum PaymentStatus {
    UNPAID, PARTPAID, PAID, DISPUTED, UNKNOWN;
}

public class Main {
    public static void main(String[] args) {
        PaymentStatus paymentStatus = PaymentStatus.PARTPAID;

        String message = switch (paymentStatus) {
        case UNPAID:
            yield "The order has not been paid yet. Please make the minimum/full amount to procced.";
        case PARTPAID:
            yield "The order is partially paid. Some features will not be available. Please check the brochure for details.";
        case PAID:
            yield "The order is fully paid. Please choose the desired items from the menu.";
        default:
            throw new IllegalStateException("Invalid payment status: " + paymentStatus);
        };

        System.out.println(message);
    }
}

Вывод:

The order is partially paid. Some features will not be available. Please check the brochure for details.

1 Поддержка String была добавлена ​​в JDK 7.

person Arvind Kumar Avinash    schedule 10.01.2021
comment
В отличие от оператора if/else if/else, оператор switch может иметь несколько возможных путей выполнения. Звучит так, будто switch может выполнять несколько случаев для одного переключателя. Если вы имеете в виду, что switch поддерживает отказоустойчивость, было бы гораздо понятнее упомянуть об этом явно. Помимо этого, if/else if/else — это просто другой синтаксис по сравнению с оператором switch, потому что вы можете легко преобразовать любой оператор switch без провала в формат if/else if/else. - person Mikko Rantalainen; 22.06.2021

Хорошая запись! Но я мог бы также добавить возможность иметь несколько вариантов для одного оператора case. Следующий пример очень надуманный (есть много лучших способов его достижения). Он просто подсчитывает частоту гласных, цифр, согласных и других символов в строке.

int count[] = new int[4];

String s = "829s2bi9jskj*&@)(so2i2ksso";

for (char c : s.toCharArray()) {
      int i = switch (c) {
                case  'a', 'e', 'i', 'o', 'u' -> 0;
                case  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> 1;
                case  'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
                      'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w',
                      'x', 'y', 'z' -> 2;
                default -> 3;
      };
      count[i]++;
}
System.out.printf("vowels  - %d%n", count[0]);
System.out.printf("digits  - %d%n", count[1]);
System.out.printf("consonants - %d%n", count[2]);
System.out.printf("other   - %d%n", count[3]);

Отпечатки

vowels  - 4
digits  - 7
consonants - 10
other   - 5
person WJS    schedule 11.01.2021

Добавление к существующим ответам: yield также можно использовать с ->, и его основная цель - разрешить использование блока, когда одного выражения недостаточно для данного случая:

var test = switch (value) {
    case A -> 1;
    case B -> 2;
    case C -> {
        System.err.println("neither A nor B"); // or some calculation
        yield -1;
    }
}

Я бы также упомянул JEP-354, где предложено и описано выражение switch.
Формальную спецификацию, как всегда, можно найти в Спецификации языка Java.

person Community    schedule 28.03.2021