switch 都支持null了,难道客官还不进来看看! Java17新特性(预览)尝鲜之switch万剑齐发 --20210811

曾几何时指北君去面试的时候,一些面试官老是问 switch 支持 String 麽之类的问题。 如今指北君想拍案而起,不要在问了,Java 中的 switch 都快支持到银河系了。什么null,Object… …等等, 已经全部支持! 下面指北君带大家看看万箭齐发的switch到底有多强。

没搞错,就是时代新贵 Java17 推出的新特性喽。虽然暂时还没有完全发布,而且是预览特性。但我们还是可以玩一玩这个飞出天际线的switch!

1. 上第一道菜 “白切贵妃鸡”垫垫肚子- switch语句的一般用法

img

第一道菜,我们来一个白切贵妃鸡(白切的,不要钱): 话不多说我们看看switch的普通用法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 public static void main(String[] args) {
        上菜(菜系.粤菜);
   }
enum 菜系{
    川菜,鲁菜,粤菜,苏菜,浙菜,闽菜,湘菜,徽菜
}
private static void 上菜(菜系 ) {
    String 出菜 = "空盘子";
    switch () {
        case 川菜:
            出菜 = "水煮肉片";
            break;
        case 鲁菜:
            出菜 = "九转大肠";
            break;
        case 粤菜:
            出菜 = "白切贵妃鸡";
            break;
        case 苏菜:
            出菜 = "水晶肴肉";
            break;
        case 浙菜:
            出菜 = "西湖醋鱼";
            break;
        case 闽菜:
            出菜 = "扳指干贝";
            break;
        case 湘菜:
            出菜 = "霸王别姬";
            break;
        case 徽菜:
            出菜 = "当归獐肉";
            break;
        default:
            throw new RuntimeException("没有菜了,陕菜来一个?");
    }
    System.out.println("客官,你要的:" + 出菜 +" 尽情品尝!");
    System.out.println("如果菜品满意,请客官素质三连!跪谢!");
}

代码中变量名使用了中文,只是为了让各位看官们不那么枯燥,顺便了解一下八大菜系。(编译需指定UTF-8字符集)

客官,白切的贵妃鸡好吃么,那么请结账: 此处由 店小二 Java12 为您服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum 指北君特色菜{
    水煮肉片,白切贵妃鸡,水晶肴肉,扳指干贝,九转大肠,西湖醋鱼,霸王别姬,当归獐肉,凉皮肉夹馍
}
private static void 结账(指北君特色菜 特色菜) {
    var 菜价 =
    switch (特色菜) {
        case 水煮肉片 -> 10000;
        case 白切贵妃鸡,水晶肴肉 -> 20000;
        case 扳指干贝,九转大肠,西湖醋鱼 -> 30000;
        case 霸王别姬,当归獐肉 -> 40000;
        case 凉皮肉夹馍 -> 15;
        default -> throw new RuntimeException("客官,你吃了空气,免费!");
    };
    System.out.println("店小二Java12 :客官,您好! 您点的 "+特色菜 + " 价值"+ 菜价/10000 + "万元人名币");
 }

连break都省了,结账块多了呢!

2. 客官吃了 白切的贵妃鸡,胃口大开,再点了 西湖醋鱼

xihucuyu

客官没吃爽,又点了西湖醋鱼。吃完菜又该结账了,店小二忙不开,请来了好徒弟 Java 14帮忙。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void 小14结账(指北君特色菜 特色菜) {
    var 菜价 =
            switch (特色菜) {
                case 水煮肉片 -> 10000;
                case 白切贵妃鸡,水晶肴肉 -> 20000;
                case 扳指干贝,九转大肠,西湖醋鱼 -> {
                    System.out.println("客官 :好吃好吃,指北君特色菜果然好吃 !!!");
                    yield 30000;
                }
                case 霸王别姬,当归獐肉 -> 40000;
                case 凉皮肉夹馍 -> {
                    System.out.println("客官 : 好吃好吃,还是凉皮肉夹馍经济实惠又好吃 !!!");
                    yield 15;
                }
                default -> throw new RuntimeException("客官,你吃了空气,免费!");
            };
    System.out.println("店小二Java14 : 客官,您好! 您点的 "+特色菜 + " 价值"+ 菜价/10000 + "万元人名币");
}

yield 返回菜价,掏空你的钱包。

3 客官用餐完毕,菜馆需要总结经验 - switch 在Java17 中如何使用。

盘点的时候看看客人吃了那些菜 ,爱吃那些菜系。 Java 17 预览小哥为您服务。请看小二如何统计。

1
2
3
4
5
6
7
8
9
10
11
12
13
enum 川菜{ 水煮肉片,麻婆豆腐,夫妻肺片 }
enum 湘菜{ 水煮肉片,麻婆豆腐,夫妻肺片 }
enum 浙菜{ 西湖醋鱼,红烧狮子头,醉虾 }

static void 客户用餐总结(Object o) {
        switch (o) {
            case null -> System.out.println("顾客喝了西北风,但是还是钟爱Java技术指北");
            case 浙菜 z  -> System.out.println("顾客爱吃浙菜");
            case 湘菜 x -> System.out.println("顾客以爱吃湘菜");
            case String s  -> System.out.println("客官重口味,爱吃川菜");
            default -> System.out.println("客户啥都吃,也爱Java技术指北!");
        };
}

Java 17 中预览版switch支持null 以及 Object 为switch中的参数,相当于在case中使用了: xxx instance of 这样的语句。

由于Switch的一些功能在Java17中暂时只是预览,如果需要使用,那么在编译的时候就需要加上 –enable-preview 的参数,具体编译代码如下。

1
openjdk-17-ea+26_windows-x64_bin\jdk-17\bin>javac --enable-preview -source 17 -encoding utf-8 SwitchTest.javaopenjdk-17-ea+26_windows-x64_bin\jdk-17\bin>javac --enable-preview -source 17 -encoding utf-8 SwitchTest.java

执行时也要启用预览功能:

1
java --enable-preview SwitchTest

4 盘点Java 17 中的 switch

4.1 支持了switch 类型检查case

示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
record Point(int i, int j) {}
enum Color { RED, GREEN, BLUE; }

static void typeTester(Object o) {
    switch (o) {
        case null     -> System.out.println("null");
        case String s -> System.out.println("String");
        case Color c  -> System.out.println("Color with " + c.values().length + " values");
        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");
    }
}

switch 中的参数使用Object, case 匹配各种类型,实则是一种类似于 instence of 的更简单的写法!

4.2 完善了switch表达式以及语句操作

例如下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void booleanSwitchTest(Object o){
	
	boolean b = false;
	String test = "" ; 
	switch (o) {
		case String s && b ->  test = "很帅";
		case String s  ->  test = "很酷";		
		default -> test = "很可爱";
	}
	
	System.out.println("Java技术指北" + test);
}

booleanSwitchTest("很有趣");//调用方法得到 "Java技术指北很酷”

可以直接返回语句处理结果。

4.3 switch case 变量的范围扩大

如果switch参数为接口或者类,则可以在case中匹配其子类,或者实现类。也可以参考上文4.1中的例子!

4.4 可以处理null的情况

case中可以对null进行判断处理,前面的示例中已经包含了相关操作,此特性请参考上文4.1种的例子!

总结

  • Java 17 中的 switch 预览版包含了大致4种switch的增强

    1. 增强了类型检查。
    2. 完善了 switch表达式 以及表达式后的语句逻辑处理。
    3. switch case 变量的范围扩大
    4. null值的处理。
  • 从JEP 406 中的未来展望可以看出,此刻switch还不支持基本类型中的boolean,float,double,但是将来肯定会找到更合适的解决方案,让switch能支持全Java系列。

  • switch支持的解决方案越多,对于开发者来说能省掉很多的代码,间接的提高工作效率,提高程序的性能。期待未来的某一天switch的火力全开版本正式发布,那一天你还会看到 Java技术指北 的再一次更全面的解说。

Java Geek Tech wechat
欢迎订阅 Java 技术指北,这里分享关于 Java 的一切。