《阿里巴巴Java開發手冊》改名《Java開發手冊》,涵蓋史無前例的三大升級


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",即可下載。趕快學起來咯~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM