天天看點

《Java 開發手冊》,向全球開發者緻敬!

緻全球Java開發者:

代碼是二進制世界的交流方式,極緻的代碼是我們的榮耀。

2017年春天,《阿裡巴巴Java開發手冊》釋出,我們希望在涵蓋程式設計規約、異常日志、單元測試、安全規約、MySQL資料庫、工程規約、設計規約等7個次元上為開發工作提供一點幫助。

目前已有超過260萬位工程師下載下傳及查閱手冊,在數以千計的企業應用,手冊成為受業界認可的開發規範。我們也有幸為全行業的研發效能、人才培養、系統穩定性作出力所能及的一點貢獻。

兩年來,Java開發者們熱心參與,以幫助這本不夠完美的手冊日臻完善。曾有開發者追蹤問題長達半年之久,反複探讨、論證其正确性。這樣的開發者難以計數,也許相隔重洋,可能相逢不識,我們用代碼确認一緻的熱愛,也讓這本手冊的價值超越了單一公司。

是以,我們決定将手冊正式更名為《Java開發手冊》,它屬于所有參與其中的貢獻者,也以此聊表我們對全球Java開發者的感謝。

《Java 開發手冊》,向全球開發者緻敬!

《Java開發手冊》正式推出更新版,涵蓋史無前例的三大更新:

1.新增21條新規約。比如,switch的空指針問題、浮點數的比較、無泛型限制引起的類型混亂、加鎖與解鎖的注意事項、YYYY的日期格式問題等;

2.修改描述112處。比如,IFNULL的判斷方式、集合的toArray的數組長度、日志占位符的處理等;

3.完善若幹處示例。比如,變量命名示例、衛語句示例、枚舉示例、finally的return示例等。

如何免費下載下傳?

《Java 開發手冊》,向全球開發者緻敬!

掃描上方二維碼

免費下載下傳《Java開發手冊》最新版

新版手冊有哪些值得關注的亮點?

首先是關于新增的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開發手冊》提供過寶貴意見與建議的所有開發者,你們是讀者,更是作者,這份榮譽屬于你們!