技術大佬:我去,你寫的 switch 語句也太老土了吧

技術大佬:我去,你寫的 switch 語句也太老土了吧

作者 | 沉默王二

來源 | CSDN 博客專家

出品 | CSDN(ID:CSDNnews)

昨天早上通過遠程的方式 review 了兩名新來同事的代碼,大部分代碼都寫得很漂亮,嚴謹的同時註釋也很到位,這令我非常滿意。但當我看到他們當中有一個人寫的 switch 語句時,還是忍不住破口大罵:“我擦,小王,你丫寫的 switch 語句也太老土了吧!”

來看看小王寫的代碼吧,看完不要罵我裝逼啊。

<code> 1private static String createPlayer(PlayerTypes playerType) {
2 switch (playerType) {
3 case TENNIS:
4 return "網球運動員費德勒";
5 case FOOTBALL:
6 return "足球運動員C羅";
7 case BASKETBALL:
8 return "籃球運動員詹姆斯";
9 case UNKNOWN:
10 throw new IllegalArgumentException("未知");
11 default:
12 throw new IllegalArgumentException(
13 "運動員類型: " + playerType);
14
15 }
16}
/<code>

看完上述代碼後,你是不是會發出這樣的感慨——“代碼寫得很好,沒有任何問題啊!”是不是覺得我在無事生非,錯怪了小王!但此時我要送上《了不起的蓋茨比》中的一句話:

我年紀還輕,閱歷不深的時候,我父親教導過我一句話,我至今還念念不忘。“每逢你想要批評任何人的時候, ”他對我說,“你就記住,這個世界上所有的人,並不是個個都有過你擁有的那些優越條件。”

哈哈,這句話不光是讓你看的,也是給我看的。是時候冷靜下來談談上述 switch 語句的老土問題了。

技术大佬:我去,你写的 switch 语句也太老土了吧

看到上圖了吧,當不小心刪掉 default 語句後,編譯器就會報錯,提示:“沒有返回語句”,為了解決這個問題,我們可以新建一個 player 變量作為返回結果,就像下面這樣:

<code> 1private static String createPlayer(PlayerTypes playerType) {
2 String player = ;
3 switch (playerType) {
4 case TENNIS:
5 player = "網球運動員費德勒";
6 break;
7 case FOOTBALL:
8 player = "足球運動員C羅";
9 break;
10 case BASKETBALL:
11 player = "籃球運動員詹姆斯";
12 break;
13 case UNKNOWN:
14 throw new IllegalArgumentException("未知");
15 }
16
17 return player;
18}
/<code>

當添加了 player 變量後,case 語句中就需要添加上 break 關鍵字;另外在 switch 語句結束後,返回 player。這時候,編譯器並不會提示任何錯誤,說明 default 語句在這種情況下是可以省略的。

從 JDK 12 開始(本例使用的是 JDK 13),switch 語句升級了,不僅可以像傳統的 switch 語句那樣作為條件的判斷,還可以直接作為一個返回結果。來對小王的代碼進行改造,如下所示:

<code> 1private static String createPlayer(PlayerTypes playerType) { 

2
3 return switch (playerType) {
4
5 case TENNIS -> "網球運動員費德勒";
6
7 case FOOTBALL -> "足球運動員C羅";
8
9 case BASKETBALL -> "籃球運動員詹姆斯";
10
11 case UNKNOWN -> throw new IllegalArgumentException("未知");
12
13 };
14
15}
/<code>

夠 fashion 吧?不僅 switch 關鍵字之前加了 return 關鍵字,case 中還見到了 Lambda 表達式的影子,中劃線和箭頭替代了冒號,意味著箭頭右側的代碼只管執行無須 break。

並且,default 語句變成了可選項,可有可無,不信?你也動手試試。

新的 switch 語句足夠的智能化,除了有上述的 3 個優勢,還可以對枚舉類型的條件進行校驗。假如在 PlayerTypes 中增加了新的類型 PINGPANG(乒乓球):

<code> 1public enum PlayerTypes {
2
3 TENNIS,
4
5 FOOTBALL,
6
7 BASKETBALL,
8
9 PINGPANG,
10
11 UNKNOWN
12

13}
/<code>

此時編譯器會發出以下警告:

技术大佬:我去,你写的 switch 语句也太老土了吧

意思就是 switch 中的 case 條件沒有完全覆蓋枚舉中可能存在的值。好吧,那就把 PINGPANG 的條件加上吧。來看一下完整的代碼:

<code> 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}
/<code>

switch 語句變成了強大的 switch 表達式,美滋滋啊!那假如一個運動員既會打籃球又會打乒乓球呢?

<code> 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}
/<code>

就像上述代碼那樣,使用英文逗號“,”把條件分割開就行了,666 啊!

不服氣?switch 表達式還有更厲害的,-> 右側還可以是 {} 括起來的代碼塊,就像 Lambda 表達式那樣。

<code> 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}
/<code>

細心的同學會發現一個之前素未謀面的關鍵字 yield,它和傳統的 return、break 有什麼區別呢?

先來看官方的解釋:

A yield statement transfers control by causing an enclosing switch expression to produce a specified value.

意思就是說 yield 語句通過使一個封閉的 switch 表達式產生一個指定值來轉移控制權。為了進一步地瞭解 yield 關鍵字,我們可以反編譯一下字節碼:

<code> 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}
/<code>

編譯器在生成字節碼的時候對 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三個有趣的平臺來給你回答!


分享到:


相關文章: