終於迎來了《Java開發手冊》的一個新的版本——泰山版。
新版本說明
此次泰山版發佈,將帶來三大亮點:新增5條日期時間規約;新增2條表別名sql規約;新增統一錯誤碼規約。
5條日期時間規約
-
【強制】日期格式化時,傳入pattern中表示年份統一使用小寫的y。
說明:日期格式化時,yyyy表示當天所在的年,而大寫的YYYY代表是week in which year(JDK7之後引入的概念),意思是當天所在的周屬於的年份,一週從週日開始,週六結束,只要本週跨年,返回的YYYY就是下一年。
正例:表示日期和時間的格式如下所示:
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
-
【強制】在日期格式中分清楚大寫的M和小寫的m,大寫的H和小寫的h分別指代的意義。
說明:日期格式中的這兩對字母表意如下:
1) 表示月份是大寫的M;
2) 表示分鐘則是小寫的m;
3) 24小時制的是大寫的H;
4) 12小時制的則是小寫的h。
-
【強制】獲取當前毫秒數:System.currentTimeMillis(); 而不是new Date().getTime()。
說明:如果想獲取更加精確的納秒級時間值,使用System.nanoTime的方式。在JDK8中,針對統計時間等場景,推薦使用Instant類。
-
【強制】不允許在程序任何地方中使用:1)java.sql.Date 2)java.sql.Time 3)java.sql.Timestamp。
說明:第1個不記錄時間,getHours()拋出異常;第2個不記錄日期,getYear()拋出異常;第3個在構造方法super((time/1000)*1000),fastTime和nanos分開存儲秒和納秒信息。
反例: java.util.Date.after(Date)進行時間比較時,當入參是java.sql.Timestamp時,會觸發JDK BUG(JDK9已修復),可能導致比較時的意外結果。
-
【強制】不要在程序中寫死一年爲365天,避免在公曆閏年時出現日期轉換錯誤或程序邏輯錯誤。
正例:
// 獲取今年的天數 int daysOfThisYear = LocalDate.now().lengthOfYear(); // 獲取指定某年的天數 LocalDate.of(2011, 1, 1).lengthOfYear();
反例:
// 第一種情況:在閏年366天時,出現數組越界異常 int[] dayArray = new int[365]; // 第二種情況:一年有效期的會員制,今年1月26日註冊,硬編碼365返回的卻是1月25日 Calendar calendar = Calendar.getInstance(); calendar.set(2020, 1, 26); calendar.add(Calendar.DATE, 365);
-
【推薦】避免公曆閏年2月問題。閏年的2月份有29天,一年後的那一天不可能是2月29日。
-
【推薦】使用枚舉值來指代月份。如果使用數字,注意Date,Calendar等日期相關類的月份month取值在0-11之間。
說明:參考JDK原生註釋,Month value is 0-based. e.g., 0 for January.
正例: Calendar.JANUARY,Calendar.FEBRUARY,Calendar.MARCH等來指代相應月份來進行傳參或比較。
2條表別名sql規約
-
【強制】對於數據庫中表記錄的查詢和變更,只要涉及多個表,都需要在列名前加表的別名(或表名)進行限定。
說明:對多表進行查詢記錄、更新記錄、刪除記錄時,如果對操作列沒有限定表的別名(或表名),並且操作列在多個表中存在時,就會拋異常。
正例:select t1.name from table_first as t1 , table_second as t2 where t1.id=t2.id;
反例:在某業務中,由於多表關聯查詢語句沒有加表的別名(或表名)的限制,正常運行兩年後,最近在某個表中增加一個同名字段,在預發佈環境做數據庫變更後,線上查詢語句出現出1052異常:Column ‘name’ in field list is ambiguous。
-
【推薦】SQL語句中表的別名前加as,並且以t1、t2、t3、…的順序依次命名。
說明:1)別名可以是表的簡稱,或者是根據表出現的順序,以t1、t2、t3的方式命名。2)別名前加as使別名更容易識別。
正例:select t1.name from table_first as t1, table_second as t2 where t1.id=t2.id;
三目運算符規範
-
【強制】三目運算符condition? 表達式1 : 表達式2中,高度注意表達式1和2在類型對齊時,可能拋出因自動拆箱導致的NPE異常。
說明:以下兩種場景會觸發類型對齊的拆箱操作:
1) 表達式1或表達式2的值只要有一個是原始類型。
2) 表達式1或表達式2的值的類型不一致,會強制拆箱升級成表示範圍更大的那個類型。
反例:
Integer a = 1; Integer b = 2; Integer c = null; Boolean flag = false; // a*b的結果是int類型,那麼c會強制拆箱成int類型,拋出NPE異常 Integer result=(flag? a*b : c);
新增統一錯誤碼規約
統一錯誤碼,就是統一度量衡,爲你的應用與服務的穩定保駕護航,煩惱清空,快樂回家。泰山版新近出爐的錯誤碼具有快速溯源、簡單易記、溝通標準化三大優勢。錯誤碼爲字符串類型,共 5 位,分成兩個部分:錯誤產生來源和四位數字編號。
錯誤產生來源分爲 A/B/C,以當前代碼運行視角來進行判定。
A 表示錯誤來源於用戶,比如請求參數錯誤,用戶安裝版本過低等問題;
B 表示錯誤來源於當前系統,往往是業務邏輯出錯,或程序健壯性差等問題;
C 表示錯誤來源於第三方服務,比如 CDN 服務出錯,消息投遞超時等問題。
優秀的錯誤碼可以迅速知道他們是怎麼來滴,從哪兒來滴,來幹啥滴。同時俺們的錯誤碼具有三級結構,分爲一級宏觀錯誤碼、二級宏觀錯誤碼、三級宏觀錯誤碼,這樣的方案更加可擴展,有彈性,更多詳細規則,見手冊的附件的《錯誤碼參考列表》。
作者QA
作者孤盡也在QA視頻中回答了新增的幾條規約實際出現過的問題。
-
在對JDK源碼閱讀技巧上給我們提了3點:
1)一定要有發現美的眼睛;
2)一定要有主線思維;
3)不斷打磨自己的基礎,包括位運算、源碼調試,甚至可以看看JVM的C++源碼或者C++下的彙編代碼。
-
你的Java開發規約在業界影響這麼大,你之前想到過有這一天嗎?
作者表示沒有想到有這麼一天,從最初的的4、5個人的小團體走到阿里巴巴,最後發到業界去,他還是堅持初心,對大家有用有幫助,繼續傳播。
-
是什麼支撐你每年推出新規約,我們知道這並不是你的本職工作。
作者表示在於兩個詞,熱愛和卓越。但是要加上形容詞。「奉獻式的熱愛」和「極致式的卓越」。
我們看到從去年的「華山版」開始,《Java開發手冊》就不再有阿里巴巴這樣的限定詞,作者的本意也是希望來致敬全球的開發者。因爲《Java開發手冊》發展到今天,已經不是單單屬於阿里巴巴或者孤盡個人,它屬於整個業界大家整體智慧的一個結晶。希望大家一起努力,將代碼演繹到極致,並寫出更優雅的代碼。
歷史版本
《Java開發手冊》一直在迭代,不知道下一個版本是什麼名字。
一起學習
最後在阿里雲開發者社區裏,也特意給我們準備了7日訓練營的打卡挑戰,幫助大家更好的理解手冊,小夥伴們一起來參加吧還有可能獲得獎品。
相關資源地址
GitHub(包含IntelliJ IDEA和Eclipse的插件):alibaba/p3c: Alibaba Java Coding Guidelines
阿里雲開發者社區:泰山版Java開發手冊-阿里雲開發者社區