java17学习笔记-switch总结
本文会介绍switch的历史。新版本更新内容及代码示例
发展史
Java 1.0(1996):首次引入switch语句,支持byte、short、char、int及枚举类型。
Java 7(2011):支持字符串类型(String)作为表达式。
Java 12(2018):引入模式匹配(第一次预览)JEP 325: Switch Expressions (Preview)
Java 13(2019):引入模式匹配(第二次预览)JEP 354: Switch Expressions (Second Preview)
Java 14(2019):引入模式匹配(上线)JEP 361: Switch Expressions
Java 17(2021):匹配增强(第一次预览)JEP 406: Pattern Matching for switch (Preview)引入保护模式和括号模式
Java 18(2021):匹配增强(第二次预览)JEP 420: Pattern Matching for switch (Second Preview)优化保护模式,表达式扩展密封类sealed
Java 19(2022):匹配增强(第三次预览)JEP 427: Pattern Matching for switch (Third Preview)引入when替换保护和括号模式,表达式拓展null
Java 20(2022):匹配增强(第四次预览)JEP 433: Pattern Matching for switch (Fourth Preview)编译检查case的详尽,表达式拓展泛型类型参数推断,记录类record
Java 21(2023):匹配增强(上线)JEP 441:交换机的模式匹配 删除括号模式,表达式拓展枚举
java12之前的switch
示例
String a = "2";switch (a) {case "1":System.out.println("it is Monday");break;case "2":System.out.println("it is Tuesday");break;case "3":System.out.println("it is Wednesday");break;case "4":System.out.println("it is Thursday");break;case "5":System.out.println("it is Friday");break;case "6":System.out.println("it is Saturday");break;case "7":System.out.println("it is Sunday");break;default:System.out.println("this is not one day of a week");break;}
也是比较常见的用法,每一个case必须要用break,当case子句未使用break时,程序会继续执行后续case的代码(称为“case穿透”)
String a = "2";switch (a) {case "1":case "2":case "3":case "4":case "5" : System.out.println("it is workday");break;case "6", "7":System.out.println("it is weekday");break;default:System.out.println("this is not one day of a week");break;}
java14第一次switch语法更新上线
引入全新模式"->" 依旧支持":"+"break"模式
String dayName = "Monday";switch (dayName) {case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"->System.out.println("Workday");case "Saturday", "Sunday"->System.out.println("Weekend");default->System.out.println(dayName + " is not a day");};
以上代码可以改写成如下,->默认带有返回值 switch 新增了返回值。
String dayName = "Monday";System.out.println(switch (dayName) {case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"->"Workday";case "Saturday", "Sunday"->"Weekend";default->dayName + " is not a day";});
还支持":"+:yield" 用于case中处理复杂逻辑之后返回
public String getDayType(String dayName) {return switch (dayName) {case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":yield "Workday";case "Saturday", "Sunday":yield "Weekday";default://模拟处理数据String resString = dayName + " is not a day";yield resString;};}
java21第二次switch语法更新上线
在JDK 14中,Switch表达式已经准备好成为最终和永久的,不再进行任何更改。
但是随着java16增强instanceof的上线switch也进行了第二次增强
java21之前如果一个对象可能属于很多种类,那么只能写很多种if else如下
static String formatter(Object o) {String formatted = "unknown";if (o instanceof Integer i) {formatted = String.format("int %d", i);} else if (o instanceof Long l) {formatted = String.format("long %d", l);} else if (o instanceof Double d) {formatted = String.format("double %f", d);} else if (o instanceof String s) {formatted = String.format("String %s", s);}return formatted;}
表达式拓展instanceof
static String formatterPatternSwitch(Object o) {return switch (o) {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();};
}
表达式拓展null
static String formatterPatternSwitch(Object o) {return switch (o) {case null -> "it is null";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();};
}
保护模式
范围越小越靠前(包括when条件和实现继承)
static void error(Object o) {switch(o) {case CharSequence cs ->System.out.println("A sequence of length " + cs.length());case String s -> // Error - pattern is dominated by previous patternSystem.out.println("A string: " + s);default -> {break;}}}
在switch加入条件函数when
(第三次预览加入代替之前使用的括号模式,且在java21发布版中括号模式删除)
static void test(Object o) {switch (o) {case String s when (s.length() == 1) -> System.out.println("传入的是String且长度为1");case String s -> System.out.println("传入的是String且长度测试");case CharSequence s -> System.out.println("mmm");default -> {System.out.println("喵喵叫");}}}
表达式拓展枚举,记录类record
record Point(int i, int j) {}enum Color { RED, GREEN, BLUE; }static void typeTester(Object obj) {switch (obj) {case null -> System.out.println("null");case String s -> System.out.println("String");case Color c -> System.out.println("Color: " + c.toString());case Point p -> System.out.println("Record class: " + p.toString());case int[] ia -> System.out.println("Array of ints of length" + ia.length);default -> System.out.println("Something else");}}
表达式拓展泛型类型参数推断
record MyPair<S,T>(S fst, T snd){};static void recordInference(MyPair<String, Integer> pair){switch (pair) {case MyPair(var f, var s) -> {System.out.println(f + " " + s);}// Inferred record Pattern MyPair<String,Integer>(var f, var s)default -> System.out.println("Something else");}}
表达式扩展密封类sealed
static void testTriangle(Shape s) {switch (s) {case Square square -> square.side();case Rectangle rectangle-> rectangle.length();case Circle circle-> circle.center();}}
public sealed interface Shape permits Circle, Rectangle, Square {}
public non-sealed class Circle implements Shape {void center() {System.out.println("圆心");}
}
public non-sealed class Rectangle implements Shape {void length() {System.out.println("长度");}
}
public final class Square implements Shape {int side;void side() {System.out.println("边长");}
}