
2019.06.19 《阿里巴巴Java開發手冊》時隔一年,發布更新1.5.0華山版。同時,將更名為《Java開發手冊》,涵蓋史無前例的三大升級
- 1)鑒於本手冊是社區開發者集體智慧的結晶,本版本移除阿里巴巴 Java 開發手冊的限定詞“阿里巴巴”。
- 2)新增 21 條新規約。比如,switch 的 NPE 問題、浮點數的比較、無泛型限制、鎖的使用方式、判斷表達式、日期格式等。
- 3)修改描述 112 處。比如,IFNULL 的判斷、集合的 toArray、日志處理等。
- 4)完善若干處示例。比如,命名示例、衛語句示例、enum 示例、finally 的 return示例等。
新版手冊有哪些值得關注的亮點?
首先是關於新增的21條故障相關的規范,全部源於業界經典事實故障,經過廣大開發者深度討論提煉而成。表面看似簡單,實質是直擊代碼靈魂的考究,唯有內功深厚之人方能看透底層。隨手列舉其中三條,一起來感受下:
1.Lock 鎖的使用往往稍微不注意,可能導致死鎖的問題。
在使用阻塞等待獲取鎖的方式中,必須在 try 代碼塊之外,並且在加鎖方法與 try 代碼塊之間沒有任何可能拋出異常的方法調用,避免加鎖成功后,在 finally 中無法解鎖。
如果在 lock 方法與 try 代碼塊之間的方法調用拋出異常,那么無法解鎖,造成其它線程無法成功獲取鎖。如果 lock 方法在 try 代碼塊之內,可能由於其它方法拋出異常,導致在 finally代碼塊中,unlock 對未加鎖的對象解鎖,它會調用 AQS 的 tryRelease 方法(取決於具體實現類),拋出 IllegalMonitorStateException 異常。在 Lock 對象的 lock方法實現中可能拋出 unchecked 異常。而在使用嘗試機制來獲取鎖的方式中,比如 tryLock(),在進入業務代碼塊之前,必須先判斷當前線程是否持有鎖。
鎖的釋放規則與鎖的阻塞等待方式相同。Lock 對象的 unlock 方法在執行時,它會調用 AQS 的 tryRelease 方法(取決於具體實現類),如果當前線程不持有鎖,則拋出 IllegalMonitorStateException 異常。
2.switch 的 NPE 問題。
當 switch 括號內的變量類型為 String 並且此變量為外部參數時,必須先進行 null 判斷。如下的代碼輸出是什么?
publicclass SwitchString {
publicstaticvoidmain(String[] args){
method(null);
}
publicstaticvoidmethod(String param){
switch(param){
// 肯定不是進入這里
case"sth":
System.out.println("it's sth");
break;
// 也不是進入這里
case"null":
System.out.println("it's null");
break;
// 也不是進入這里
default:
System.out.println("default");
}
}
}
3.浮點數的比較問題。
1-0.9=0.1是天經地義的,但在計算機的世界里,0.1恰恰是無法精確表示的一個小數,只有2的冪次倍小數才能夠精確表示,如:0.5、0.25、0.125等。由於0.1是近似表達,在各種情形中的計算存在數位的取舍精度不一樣,所以1-0.9未必等於0.9-0.8,所以浮點數之間的等值判斷,基本數據類型不能用==來比較,包裝數據類型不能用equals來判斷。
說明:浮點數采用“尾數+階碼”的編碼方式,類似於科學計數法的“有效數字+指數”的表示方式。二進制無法精確表示大部分的十進制小數,具體原理參考《碼出高效》。示例如下:
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
if (a == b) {
// 預期進入此代碼塊,執行其它業務邏輯
// 但是 a==b 的結果為false
}
Float x = Float.valueOf(a);
Float y = Float.valueOf(b);
if (x.equals(y)) {
// 預期進入此代碼塊,執行其它業務邏輯
// 但是 x.equals(y) 的結果為false
}
《Java開發手冊》自始至終不是最完美的,但是有了業界所有開發者的關注與支持,我們相信它在一步步走向完美。在廣大開發者的建議下,此次“華山版”修正了過往歷史版本的兩個錯誤。
1.集合轉數組時的傳入數組的空間設置。有讀者追蹤這個問題長達半年之久,大家可以到P3C的ISSUE里找到關於這段論戰的歷史軌跡。他指出,toArray 的數組長度必須設置為0。后來我們發現在高並發情況下,他的說法是對的。
2.關於 ScheduleService 的刪除。關於這個方法創建線程池,雖然可以模仿出來它的 OOM 情況,但是找遍 JDK 沒有任何替代的方式。所以我們回到它的原點問題上,深入地思考會不會有人使用 ScheduleService 的方式,不斷地加入隊列中呢?它是一個定時執行的線程池,這種操作方式是不是過於暴力、為賦新詞強說愁?權衡之下,最后新版手冊去掉這條規約的檢測。
為了讓更多基礎入門的開發者能更快、准確理解規約背后的思路,此次新版也對部分略顯艱澀的示例做了更生動的解釋。以貼合實際生活場景的視角,幫助讀者理解代碼世界中的邏輯原理。
比如,關於衛語句的說明,原來的例子理解起來是有難度的,修正為從女孩子相親的視角來看待。在嵌套語句的要求中,如果非得使用 if()…else if()…else…方式表達邏輯,請勿超過3層,超過請使用狀態設計模式。超過3層的 if-else 的邏輯判斷代碼可以使用衛語句、策略模式、狀態模式等來實現,其中衛語句示例如下:
public class GuardSatementsDemo{
public void findBoyfriend(Man man) {
if(man.isBadTemper()) {
System.out.println(“月球有多遠,你就給我滾多遠.”);
return;
}
if (man.isShort()) {
System.out.println(“我不需要武大郎一樣的男友.”);
return;
}
if (man.isPoor()) {
System.out.println(“貧賤夫妻百事哀.”);
return;
}
System.out.println(“可以先交往一段時間看看.”);
}
}
看了這么多新特性,那必須得花上喝咖啡的時間,學習一下,為自己寫的程序保駕護航。
最新版的領取方式:微信關注"Java技術干貨",回復"book001",即可下載。趕快學起來咯~~~

