什么是 switch 表达式,它们与 switch 语句有何不同?

Posted

技术标签:

【中文标题】什么是 switch 表达式,它们与 switch 语句有何不同?【英文标题】:What are switch expressions and how are they different from switch statements? 【发布时间】:2021-04-15 19:46:10 【问题描述】:

作为 Java SE 12 的一部分,引入了 switch expressions,并且自 Java SE 14 起,它们已被标准化。它们与switch 语句有何不同?

【问题讨论】:

标准化与引入是什么意思? @rogerdpack 这必须指的是作为 JDK 12 中的预览功能引入的 switch 表达式 - 完全可用和完整,通过编译器选项启用,仍然可以根据用户反馈在未来版本中进行(重大)更改.在 JDK 14 中,这被整合为一个标准特性,在未来的版本中不会再改变。 【参考方案1】:

switch 声明:

if/else if/else 语句不同,switch 语句可以有多个可能的执行路径。 switch 适用于原始类型 byteshortcharint,它们各自的包装类型(ByteShortCharacterInteger),枚举类型和String 类型1if-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 中引入的。但是,它仍然作为 Java SE 12 和 13 中的预览功能,最终在 Java SE 14 中实现了标准化。Like any expression,@ 987654341@ 表达式计算为单个值,并且可以在语句中使用。它还引入了“箭头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 JDK 7 添加了对String 的支持

【讨论】:

“与 if/else if/else 语句不同,switch 语句可以有许多可能的执行路径”听起来像switch 可以为一个 switch 执行多个 case。如果您的意思是 switch 支持失败,那么明确提及这一点会更清楚。除此之外,if/else if/else 只是与 switch 语句不同的语法,因为您可以轻松地将任何 switch 语句转换为 if/else if/else 格式。【参考方案2】:

写得真好!但我也可以为单个案例语句添加多个案例的能力。下面的例子非常做作(有很多更好的方法可以实现)。它对字符串中的元音、数字、辅音和其他字符进行简单的频率计数。

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

【讨论】:

【参考方案3】:

添加到现有答案: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,其中提出和描述了开关表达式。 可以在Java Language Specification 中找到正式规范。

【讨论】:

以上是关于什么是 switch 表达式,它们与 switch 语句有何不同?的主要内容,如果未能解决你的问题,请参考以下文章

c语言中switch的用法 c语言中switch怎么使用

switch语句怎么用啊 具体啊!

switch语句的用法?

switch与java

switch用法

golang减少switch