技術大佬:我去,你寫的 switch 語句也太老土了吧
昨天早上通過遠端的方式 review 了兩名新來同事的程式碼,大部分程式碼都寫得很漂亮,嚴謹的同時註釋也很到位,這令我非常滿意。但當我看到他們當中有一個人寫的 switch 語句時,還是忍不住破口大罵:“我擦,小王,你丫寫的 switch 語句也太老土了吧!”
來看看小王寫的程式碼吧,看完不要罵我裝逼啊。
private static String createPlayer(PlayerTypes playerType) {
switch (playerType) {
case TENNIS:
return "網球運動員費德勒";
case FOOTBALL:
return "足球運動員C羅";
case BASKETBALL:
return "籃球運動員詹姆斯";
case UNKNOWN:
throw new IllegalArgumentException("未知");
default:
throw new IllegalArgumentException(
"運動員型別: " + playerType);
}
}
看完上述程式碼後,你是不是會發出這樣的感慨——“程式碼寫得很好,沒有任何問題啊!”是不是覺得我在無事生非,錯怪了小王!但此時我要送上《了不起的蓋茨比》中的一句話:
我年紀還輕,閱歷不深的時候,我父親教導過我一句話,我至今還念念不忘。 “每逢你想要批評任何人的時候, ”他對我說,“你就記住,這個世界上所有的人,並不是個個都有過你擁有的那些優越條件。”
哈哈,這句話不光是讓你看的,也是給我看的。是時候冷靜下來談談上述 switch 語句的老土問題了。
看到上圖了吧,當不小心刪掉 default 語句後,編譯器就會報錯,提示:“沒有返回語句”,為了解決這個問題,我們可以新建一個 player 變數作為返回結果,就像下面這樣:
private static String createPlayer(PlayerTypes playerType) {
String player = null;
switch (playerType) {
case TENNIS:
player = "網球運動員費德勒";
break;
case FOOTBALL:
player = "足球運動員C羅";
break;
case BASKETBALL:
player = "籃球運動員詹姆斯";
break;
case UNKNOWN:
throw new IllegalArgumentException("未知");
}
return player;
}
當新增了 player 變數後,case 語句中就需要新增上 break 關鍵字;另外在 switch 語句結束後,返回 player。這時候,編譯器並不會提示任何錯誤,說明 default 語句在這種情況下是可以省略的。
從 JDK 12 開始(本例使用的是 JDK 13),switch 語句升級了,不僅可以像傳統的 switch 語句那樣作為條件的判斷,還可以直接作為一個返回結果。來對小王的程式碼進行改造,如下所示:
private static String createPlayer(PlayerTypes playerType) {
return switch (playerType) {
case TENNIS -> "網球運動員費德勒";
case FOOTBALL -> "足球運動員C羅";
case BASKETBALL -> "籃球運動員詹姆斯";
case UNKNOWN -> throw new IllegalArgumentException("未知");
};
}
夠 fashion 吧?不僅 switch 關鍵字之前加了 return 關鍵字,case 中還見到了 Lambda 表示式的影子,中劃線和箭頭替代了冒號,意味著箭頭右側的程式碼只管執行無須 break。
並且,default 語句變成了可選項,可有可無,不信?你也動手試試。
新的 switch 語句足夠的智慧化,除了有上述的 3 個優勢,還可以對列舉型別的條件進行校驗。假如在 PlayerTypes 中增加了新的型別 PINGPANG(乒乓球):
public enum PlayerTypes {
TENNIS,
FOOTBALL,
BASKETBALL,
PINGPANG,
UNKNOWN
}
此時編譯器會發出以下警告:
意思就是 switch 中的 case 條件沒有完全覆蓋列舉中可能存在的值。好吧,那就把 PINGPANG 的條件加上吧。來看一下完整的程式碼:
public class OldSwitchDemo {
public enum PlayerTypes {
TENNIS,
FOOTBALL,
BASKETBALL,
PINGPANG,
UNKNOWN
}
public static void main(String[] args) {
System.out.println(createPlayer(PlayerTypes.BASKETBALL));
}
private static String createPlayer(PlayerTypes playerType) {
return switch (playerType) {
case TENNIS -> "網球運動員費德勒";
case FOOTBALL -> "足球運動員C羅";
case BASKETBALL -> "籃球運動員詹姆斯";
case PINGPANG -> "乒乓球運動員馬龍";
case UNKNOWN -> throw new IllegalArgumentException("未知");
};
}
}
switch 語句變成了強大的 switch 表示式,美滋滋啊!那假如一個運動員既會打籃球又會打乒乓球呢?
private static String createPlayer(PlayerTypes playerType) {
return switch (playerType) {
case TENNIS -> "網球運動員費德勒";
case FOOTBALL -> "足球運動員C羅";
case BASKETBALL,PINGPANG -> "牛逼運動員沉默王二";
case UNKNOWN -> throw new IllegalArgumentException("未知");
};
}
就像上述程式碼那樣,使用英文逗號“,”把條件分割開就行了,666 啊!
不服氣?switch 表示式還有更厲害的,->
右側還可以是 {}
括起來的程式碼塊,就像 Lambda 表示式那樣。
private static String createPlayer(PlayerTypes playerType) {
return switch (playerType) {
case TENNIS -> {
System.out.println("網球");
yield "網球運動員費德勒";
}
case FOOTBALL -> {
System.out.println("足球");
yield "足球運動員C羅";
}
case BASKETBALL -> {
System.out.println("籃球");
yield "籃球運動員詹姆斯";
}
case PINGPANG -> {
System.out.println("乒乓球");
yield "乒乓球運動員馬龍";
}
case UNKNOWN -> throw new IllegalArgumentException("未知");
};
}
細心的同學會發現一個之前素未謀面的關鍵字 yield
,它和傳統的 return、break 有什麼區別呢?
先來看官方的解釋:
A yield statement transfers control by causing an enclosing switch expression to produce a specified value.
意思就是說 yield 語句通過使一個封閉的 switch 表示式產生一個指定值來轉移控制權。為了進一步地瞭解 yield
關鍵字,我們可以反編譯一下位元組碼:
private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) {
String var10000;
switch(playerType) {
case TENNIS:
System.out.println("網球");
var10000 = "網球運動員費德勒";
break;
case FOOTBALL:
System.out.println("足球");
var10000 = "足球運動員C羅";
break;
case BASKETBALL:
System.out.println("籃球");
var10000 = "籃球運動員詹姆斯";
break;
case PINGPANG:
System.out.println("乒乓球");
var10000 = "乒乓球運動員馬龍";
break;
case UNKNOWN:
throw new IllegalArgumentException("未知");
default:
throw new IncompatibleClassChangeError();
}
return var10000;
}
編譯器在生成位元組碼的時候對 yield
關鍵字做了自動化轉義,轉成了傳統的 break 語句。這下清楚了吧?
但是,話又說出來,那些看似 fashion 的程式碼也不過是把部分秀技的工作交給了編譯器,還可能存在對舊版本不相容、對隊友不友好的問題——程式碼土點就土點唄,沒準是最實用的。
“不好意思,我為昨天早上的囂張向你道歉。。。。。。”我向小王傳送了一條資訊。
好了,我親愛的讀者朋友,以上就是本文的全部內容了,希望能夠博得你的歡心。
最後,一定會有不少讀者想要問我怎麼學習 Java 的,那我乾脆就把我看過的優質書籍貢獻出來:
1)入門版:《Head First Java》、《Java 核心技術卷》
2)進階版:《Java程式設計思想》、《Effective Java》、《Java網路程式設計》、《程式碼整潔之道》
3)大牛版:《Java併發程式設計》、《深入理解Java虛擬機器》、《Java效能權威指南》、《重構》、《演算法》
就先介紹這麼多,希望對那些不知道看什麼書的同學有所幫助。
對了,我介紹的這些書籍,已經順便幫你整理好了,你可以在我的原創微信公眾號『沉默王二』回覆『書籍』獲取哦
有收穫?希望老鐵們來個三連擊,給更多的同學看到這篇文章
相關文章
- 技術大佬:我去,你竟然還不會用 this 關鍵字
- switch語句的妙用
- JavaScript switch 語句JavaScript
- JavaScript switch語句JavaScript
- Go switch 語句Go
- JavaScript中的switch語句JavaScript
- golang中一種不常見的switch語句寫法Golang
- SQL 語句寫的爛怎麼辦?我幫你解決?SQL
- 別太把技術當回事 也別不把技術當回事
- switch語句逆向分析
- java中的switch case語句Java
- 哇塞!GitHub 上這些 Java repo 太強了吧,看完哪個都變大佬!GithubJava
- Matlab的if語句switch語句for迴圈while迴圈語句練習MatlabWhile
- [譯] part 10: switch 語句
- 你現在不用寫程式碼了吧?
- 程式碼review,程式碼審查,用upsource 也太方便了吧View
- java switch語句是什麼?Java
- java中switch語句注意--breakJava
- Java 判斷語句 - if…else/switchJava
- 第 7 小節 if、switch 語句
- JAVA基礎--Switch case語句Java
- JavaScript switch與if else語句的區別JavaScript
- [譯] 為什麼我更喜歡物件而不是switch語句物件
- Java學習之分支結構---判斷語句:if語句和switch語句Java
- 太可怕,這項技術僅透過語音就能勾勒出你的長相
- 從 HTTP 切換到 HTTPS,這下我的技術部落格安全了吧?HTTP
- 清華尹成帶你實戰GO案例(16)Go Switch語句Go
- SQL語句優化技術分析SQL優化
- printf格式控制、switch-case語句
- switch case語句程式碼例項
- js switch語句需要特別注意的地方JS
- 技術無罪的switch破解
- JavaScript 流程控制語句詳解:if語句、switch語句、while迴圈、for迴圈等JavaScriptWhile
- 我常用經典SQL語句[就先寫一句吧]SQL
- 談談SQL 語句的優化技術 (2)SQL優化
- 談談SQL 語句的優化技術 (1)SQL優化
- SQL語句最佳化技術分析SQL
- ORACLE SQL語句優化技術分析OracleSQL優化