Switch模式匹配Java21正式推出

23-03-09 banq

switch 通过表达式和语句的模式匹配增强 Java 编程语言。将模式匹配扩展为switch允许针对多个模式测试表达式,每个模式具有特定的操作,以便可以简洁、安全地表达复杂的面向数据的查询。

模式匹配由JEP 406switch提出 ,随后在 JEP 420、427433 中得到完善[url=https://openjdk.org/jeps/427]。[/url]它与记录模式功能(JEP 8300541 草案)共同发展,因为这两个功能之间存在相当大的交互。此 JEP 建议根据持续的经验和反馈,通过进一步的小改进来最终在Java 21中确定该功能。

Java 21以前:

// Prior to Java 21
static String formatter(Object obj) {
    String formatted = "unknown";
    if (obj instanceof Integer i) {
        formatted = String.format("int %d", i);
    } else if (obj instanceof Long l) {
        formatted = String.format("long %d", l);
    } else if (obj instanceof Double d) {
        formatted = String.format("double %f", d);
    } else if (obj instanceof String s) {
        formatted = String.format("String %s", s);
    }
    return formatted;
}

这段代码受益于使用模式instanceof表达式,但它远非完美。

switch对于模式匹配来说是绝配!如果我们扩展switch 语句和表达式以适用于任何类型,并允许case带有模式的标签而不仅仅是常量,那么我们可以更清晰可靠地重写上面的代码:

// As of Java 21
static String formatterPatternSwitch(Object obj) {
    return switch (obj) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}


这段代码的意图更加清晰,因为我们使用了正确的控制结构:我们说,“参数obj最多匹配以下条件之一,找出并评估相应的结果。” 作为奖励,它更易于优化;在这种情况下,我们更有可能在O (1) 时间内执行调度。

空指针
Java21以前, 如果选择器表达式的计算结果为,则switch语句和表达式会抛出,因此必须在 之外进行测试:NullPointerExceptionnullnullswitch

// Prior to Java 21
static void testFooBar(String s) {
    if (s == null) {
        System.out.println("Oops!");
        return;
    }
    switch (s) {
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}


switch当仅支持少数引用类型时,这是合理的。但是,如果switch允许任何引用类型的选择器表达式,并且case 标签可以有类型模式,那么独立null测试感觉就像是一种任意区分,并且会引入不必要的样板代码和出错的机会。

// As of Java 21
static void testFooBar(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}



详细点击标题