文章目录
- 传统switch声明语句的弊端:
- JDK12中预览特性:
- JDK13
- **JDK17的预览特性:switch的模式匹配**
传统switch声明语句的弊端:
- 匹配是自上而下的,如果忘记写break,后面的case语句不论匹配与否都会执行; —>case穿透
- 所有的case语句共用一个块范围,在不同的case语句定义的变量名不能重复;
- 不能在一个case里写多个执行结果一致的条件;
- 整个switch不能作为表达式返回值;
//常见错误实现
switch(month){case 3|4|5://3|4|5 用了位运算符,11 | 100 | 101结果是 111是7System.out.println("春季");break;case 6|7|8://6|7|8用了位运算符,110 | 111 | 1000结果是1111是15System.out.println("夏季");break;case 9|10|11://9|10|11用了位运算符,1001 | 1010 | 1011结果是1011是11System.out.println("秋季");break;case 12|1|2://12|1|2 用了位运算符,1100 | 1 | 10 结果是1111,是15System.out.println("冬季");break;default:System.out.println("输入有误");
}
JDK12中预览特性:
-
Java 12将会对switch声明语句进行扩展,使用
case L ->
来替代以前的break;
,省去了 break 语句,避免了因少写 break 而出错。 -
同时将多个 case 合并到一行,显得简洁、清晰,也更加优雅的表达逻辑分支。
-
为了保持兼容性,case 条件语句中依然可以使用字符
:
,但是同一个 switch 结构里不能混用->
和:
,否则编译错误。
举例:
Java 12之前
public class SwitchTest {public static void main(String[] args) {int numberOfLetters;Fruit fruit = Fruit.APPLE;switch (fruit) {case PEAR:numberOfLetters = 4;break;case APPLE:case GRAPE:case MANGO:numberOfLetters = 5;break;case ORANGE:case PAPAYA:numberOfLetters = 6;break;default:throw new IllegalStateException("No Such Fruit:" + fruit);}System.out.println(numberOfLetters);}
}
enum Fruit {PEAR, APPLE, GRAPE, MANGO, ORANGE, PAPAYA;
}
switch 语句如果漏写了一个 break,那么逻辑往往就跑偏了,这种方式既繁琐,又容易出错。
Java 12中:
public class SwitchTest1 {public static void main(String[] args) {Fruit fruit = Fruit.GRAPE;switch(fruit){case PEAR -> System.out.println(4);case APPLE,MANGO,GRAPE -> System.out.println(5);case ORANGE,PAPAYA -> System.out.println(6);default -> throw new IllegalStateException("No Such Fruit:" + fruit);};}
}
更进一步:
public class SwitchTest2 {public static void main(String[] args) {Fruit fruit = Fruit.GRAPE;int numberOfLetters = switch(fruit){case PEAR -> 4;case APPLE,MANGO,GRAPE -> 5;case ORANGE,PAPAYA -> 6;default -> throw new IllegalStateException("No Such Fruit:" + fruit);};System.out.println(numberOfLetters);}
}
JDK13
JDK13中引入了yield语句,用于返回值。这意味着,switch表达式(返回值)应该使用yield,switch语句(不返回值)应该使用break。
yield和return的区别在于:return会直接跳出当前循环或者方法,而yield只会跳出当前switch块。
在以前:
@Test
public void testSwitch1(){String x = "3";int i;switch (x) {case "1":i=1;break;case "2":i=2;break;default:i = x.length();break;}System.out.println(i);
}
在JDK13中:
@Test
public void testSwitch2(){String x = "3";int i = switch (x) {case "1" -> 1;case "2" -> 2;default -> {yield 3;}};System.out.println(i);
}
或者
@Test
public void testSwitch3() {String x = "3";int i = switch (x) {case "1":yield 1;case "2":yield 2;default:yield 3;};System.out.println(i);
}
JDK17的预览特性:switch的模式匹配
旧写法:
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;
}
模式匹配新写法:
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();};
}
直接在 switch 上支持 Object 类型,这就等于同时支持多种类型,使用模式匹配得到具体类型,大大简化了语法量,这个功能很实用。