作者|沉默的国王二
来源| CSDN博主
CSDN(ID:CSDNnews)
昨天早上,我远程查看了两个新同事的代码。大部分代码写得很漂亮,很严谨,评论也很好,让我很满意。但当我看到其中一个人写的switch声明时,我忍不住破口大骂:“我靠,小王,你写的switch声明太老套了!”
看看小王写的代码。看完不要骂我装逼。
1私有静态字符串create player(player types player type){
2个开关(播放器类型){
3箱网球:
4‘网球运动员费德勒’;
5格足球:
6‘足球运动员罗纳尔多’;
7格篮球:
8‘篮球运动员詹姆斯’;
9个未知病例:
1 row New IllegalArgumentException(“unknown”);
11默认值:
12抛出新的IllegalArgumentException(
13 \'运动员型3360 \'选手型);
14
15 }
16}看完上面的代码,你会发出——“代码写得很好,没有问题!”你觉得我在大惊小怪吗?我错怪小王了!但此时,我想送你《了不起的盖茨比》的一句话:
在我年少无知的时候,父亲教过我一句话,我至今记忆犹新。“无论何时你想批评任何人,”他对我说,“记住,这个世界上并不是所有的人都拥有你所拥有的优势。”
哈哈,这句话不仅是给你的,也是给我的。是时候静下心来说说上面switch语句的老套问题了。
看到上图了吗?当默认语句被意外删除时,编译器会报错,提示:“没有返回语句”。为了解决这个问题,我们可以创建一个新的玩家变量作为返回结果,如下所示:
1私有静态字符串create player(player types player type){
2字符串播放器=;
3开关(播放器类型){
4箱网球:
5球员=‘网球运动员费德勒’;
6破;
7格足球:
8球员=‘足球运动员c罗’;
9断;
10盒篮球:
1player=\'篮球运动员詹姆斯\';
12断;
13个未知病例:
1 row new IllegalArgumentException(“未知”);
15 }
16
17回球员;
18}加入player变量时,需要在case语句中加入break关键字;另外,switch语句结束后,播放器返回。此时编译器不会提示任何错误,表示这种情况下可以省略default语句。
从JDK 12开始(本例中使用的是JDK 13),switch语句已经升级。它既可以像传统的switch语句一样作为条件判断,也可以直接作为返回结果。对小王的代码进行如下转换:
1私有静态字符串create player(player types player type){
2
3返回开关(playerType) {
四
5格网球——‘网球运动员费德勒’;
六
7案例足球——‘足球运动员c罗’;
八
9格篮球——‘篮球运动员詹姆斯’;
10
1 case unknown-抛出新的illegalargumentException(“unknown”);
br>1213 };
14
15}
够 fashion 吧?不仅 switch 关键字之前加了 return 关键字,case 中还见到了 Lambda 表达式的影子,中划线和箭头替代了冒号,意味着箭头右侧的代码只管执行无须 break。
并且,default 语句变成了可选项,可有可无,不信?你也动手试试。
新的 switch 语句足够的智能化,除了有上述的 3 个优势,还可以对枚举类型的条件进行校验。假如在 PlayerTypes 中增加了新的类型 PINGPANG(乒乓球):
1public enum PlayerTypes {
2
3 TENNIS,
4
5 FOOTBALL,
6
7 BASKETBALL,
8
9 PINGPANG,
10
11 UNKNOWN
12
13}
此时编译器会发出以下警告:
意思就是 switch 中的 case 条件没有完全覆盖枚举中可能存在的值。好吧,那就把 PINGPANG 的条件加上吧。来看一下完整的代码:
1public class OldSwitchDemo {
2
3 public enum PlayerTypes {
4
5 TENNIS,
6
7 FOOTBALL,
8
9 BASKETBALL,
10
11 PINGPANG,
12
13 UNKNOWN
14
15 }
16
17
18
19 public static void main(String[] args) {
20
21 System.out.println(createPlayer(PlayerTypes.BASKETBALL));
22
23 }
24
25
26
27 private static String createPlayer(PlayerTypes playerType) {
28
29 return switch (playerType) {
30
31 case TENNIS -> \"网球运动员费德勒\";
32
33 case FOOTBALL -> \"足球运动员C罗\";
34
35 case BASKETBALL -> \"篮球运动员詹姆斯\";
36
37 case PINGPANG -> \"乒乓球运动员马龙\";
38
39 case UNKNOWN -> throw new IllegalArgumentException(\"未知\");
40
41 };
42
43 }
44
45}
switch 语句变成了强大的 switch 表达式,美滋滋啊!那假如一个运动员既会打篮球又会打乒乓球呢?
1private static String createPlayer(PlayerTypes playerType) {
2
3 return switch (playerType) {
4
5 case TENNIS -> \"网球运动员费德勒\";
6
7 case FOOTBALL -> \"足球运动员C罗\";
8
9 case BASKETBALL,PINGPANG -> \"牛逼运动员沉默王二\";
10
11 case UNKNOWN -> throw new IllegalArgumentException(\"未知\");
12
13 };
14
15}
就像上述代码那样,使用英文逗号“,”把条件分割开就行了,666 啊!
不服气?switch 表达式还有更厉害的,-> 右侧还可以是 {} 括起来的代码块,就像 Lambda 表达式那样。
1private static String createPlayer(PlayerTypes playerType) {
2
3 return switch (playerType) {
4
5 case TENNIS -> {
6
7 System.out.println(\"网球\");
8
9 yield \"网球运动员费德勒\";
10
11 }
12
13 case FOOTBALL -> {
14
15 System.out.println(\"足球\");
16
17 yield \"足球运动员C罗\";
18
19 }
20
21 case BASKETBALL -> {
22
23 System.out.println(\"篮球\");
24
25 yield \"篮球运动员詹姆斯\";
26
27 }
28
29 case PINGPANG -> {
30
31 System.out.println(\"乒乓球\");
32
33 yield \"乒乓球运动员马龙\";
34
35 }
36
37 case UNKNOWN -> throw new IllegalArgumentException(\"未知\");
38
39 };
40
41}
细心的同学会发现一个之前素未谋面的关键字 yield,它和传统的 return、break 有什么区别呢?
先来看官方的解释:
A yield statement transfers control by causing an enclosing switch expression to produce a specified value.
意思就是说 yield 语句通过使一个封闭的 switch 表达式产生一个指定值来转移控制权。为了进一步地了解 yield 关键字,我们可以反编译一下字节码:
1private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) {
2
3 String var10000;
4
5 switch(playerType) {
6
7 case TENNIS:
8
9 System.out.println(\"网球\");
10
11 var10000 = \"网球运动员费德勒\";
12
13 break;
14
15 case FOOTBALL:
16
17 System.out.println(\"足球\");
18
19 var10000 = \"足球运动员C罗\";
20
21 break;
22
23 case BASKETBALL:
24
25 System.out.println(\"篮球\");
26
27 var10000 = \"篮球运动员詹姆斯\";
28
29 break;
30
31 case PINGPANG:
32
33 System.out.println(\"乒乓球\");
34
35 var10000 = \"乒乓球运动员马龙\";
36
37 break;
38
39 case UNKNOWN:
40
41 throw new IllegalArgumentException(\"未知\");
42
43 default:
44
45 throw new IncompatibleClassChangeError;
46
47 }
48
49
50
51 return var10000;
52
53}
编译器在生成字节码的时候对 yield 关键字做了自动化转义,转成了传统的 break 语句。这下清楚了吧?
但是,话又说出来,那些看似 fashion 的代码也不过是把部分秀技的工作交给了编译器,还可能存在对旧版本不兼容、对队友不友好的问题——代码土点就土点呗,没准是最实用的。
“不好意思,我为昨天早上的嚣张向你道歉。。。。。。”我向小王发送了一条信息。
好了,我亲爱的读者朋友,以上就是本文的全部内容了,希望你学得开心。
原文链接:
https://blog.csdn.net/qing_gee/article/details/104586826
☞华为补助武汉员工,最高每日 2000 元;iPhone SE 2 量产或推迟;PowerShell 7.0 发布 | 极客头条
☞腾讯云“抢救”微盟!开 766 次在线会议、调拨 100 多台服务器、闹钟只敢定 2 小时
☞人工智能改变未来教育的5大方式!
☞Linux 会成为主流桌面操作系统吗?
☞6 个步骤,教你在Ubuntu虚拟机环境下,用Docker自带的DNS配置Hadoop | 附代码
☞开发项目时如何选择区块链平台?我们分析了以太坊、Bitcoin via RSK、Ardor三个有趣的平台来给你回答!