速來,圍觀阿里出品的泰山版Java開發手冊

說起華山,我就想起嶽不羣,不,令狐沖;說起泰山,我就想起司馬遷,他的那句名言“人總有一死,或重於泰山,或輕於鴻毛”,真的發人深省啊。這就意味着,阿里出品的泰山版 Java 開發手冊,是迄今爲止最重量級的。

華山版是上個版本,啥時候更新的呢?2019 年 06 月 13 號,距離現在 10 個月了,時間也不短了,是時候推陳出新了。

新版都更新了哪些內容呢?可以從官方的版本歷史中看得出來。

01、發佈錯誤碼統一解決方案

錯誤碼用來幹嘛呢?答案是異常日誌,方便我們快速知曉錯誤來源,判斷是誰那出的問題。上圖中 A 表示錯誤來源於用戶;還有 B 級的,表示錯誤來源於當前系統;C 級的,表示錯誤來源於第三方服務,比如 CDN 服務器。

這個解決方案還是值得借鑑的,很多成熟的系統都在使用錯誤碼,如果你對接過微信支付的話,應該對錯誤碼不會感到陌生。看到錯誤碼,然後在手冊中搜索一下,就能快速知曉錯誤的類型,還是很不錯的。

02、新增 34 條新的規約

34 條太多了,我就挑幾個重要的拉出來說一說吧。

1)日期時間

還記得上次技術圈的刷屏事件吧?就是那個 YYYY 和 yyyy 造成的問題。大寫的 Y 表示的是當天所在的這一週是屬於哪個年份的,小寫的 y 表示的是當天所在的年份,差別還是挺大的。你品,你細品。

還有,大寫的 M 和 小寫的 m 是不同的,大寫的 H 和小寫的 h 也是不同的。

另外,像獲取當前毫秒數應該使用 System.currentTimeMillis(),而不是 new Date().getTime(),這些細緻的規約,都應該牢記在心中,不要去犯這些低級的錯誤。

2)三目運算的 NPE 問題

說實話,這個問題我之前從來沒有注意,這次看到了,就一起來學習一下。先來看下面這段代碼:

public class TestCondition {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = null;
        Boolean flag = false;
        Integer result = flag ? a * b : c;
    }
}

條件 a * b 屬於算術運算,它倆相乘後的結果是一個 int 類型,這就會導致 c 這個 Integer 類型自動拆箱,由於值爲 null,就拋出了以下錯誤:

Exception in thread "main" java.lang.NullPointerException
	at com.cmower.mkyong.TestCondition.main(TestCondition.java:9)

那可能你會感到好奇,爲什麼兩個 Integer 類型的變量相乘後會是一個 int 類型呢,這主要是由編譯器決定的,它就是這麼設計的,來看一下反編譯後的字節碼:

public class TestCondition
{
    public static void main(String args[])
    {
        Integer a = Integer.valueOf(1);
        Integer b = Integer.valueOf(2);
        Integer c = null;
        Boolean flag = Boolean.valueOf(false);
        Integer result = Integer.valueOf(flag.booleanValue() ? a.intValue() * b.intValue() : c.intValue());
    }
}

a * b 時發生了自動拆箱,調用了 intValue() 方法,而三元運算的兩個表達式的類型必須一致,這就導致 c 也調用了 intValue() 方法,由於 c 本身爲 null,那就只能 NPE 了。明白了吧?

3)Collectors 類的 toMap() 方法

手冊上說,在使用 java.util.stream.Collectors 類的 toMap() 方法轉 Map 時,一定要使用含有參數類型爲 BinaryOperator,參數名爲 mergeFunction 的方法,否則當出現相同 key 值時會拋出 IllegalStateException 異常。

這段話可能理解上有點難度,那先來看一段代碼吧!

String[] departments = new String[] {"沉默王二", "沉默王二", "沉默王三"};
Map<Integer, String> map = Arrays.stream(departments)
        .collect(Collectors.toMap(String::hashCode, str -> str));

運行這段代碼的時候,就會拋出異常,堆棧信息如下所示:

Exception in thread "main" java.lang.IllegalStateException: Duplicate key 867758096 (attempted merging values 沉默王二 and 沉默王二)
	at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133)
	at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180)

key 重複了,因爲兩個“沉默王二”的 hashCode 相同,那這時候的解決辦法呢?

String[] departments = new String[] {"沉默王二", "沉默王二", "沉默王三"};
Map<Integer, String> map = Arrays.stream(departments)
        .collect(Collectors.toMap(String::hashCode, str -> str, (v1, v2) -> v2));

多加個參數 (v1, v2) -> v2,也就是重複的時候選一個。來看看此時調用的 toMap() 方法吧。

public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper,
                                BinaryOperator<U> mergeFunction) {
    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

BinaryOperator 和 mergeFunction 是不是出現了?

03、修改描述 90 處

手冊上說,比如,阻塞等待鎖、建表的小數類型等描述有修改,我特麼花了半個小時也沒有找出來和上一個版本之間的差別。

泰山版

華山版

不知道是不是手冊的小編在瞎說,你要是能發現差別,告訴我一聲。

04、完善若干處示例

比如說 SQL 語句欄目裏的 ISNULL 的示例,確實比華山版追加了一個更詳細的反例,見下圖。

但說實話,這段反例的描述我看了至少六遍才搞懂是什麼意思。首先,不要在 null 前換行,影響閱讀性,這倒是真的;其次呢,不要使用 column is null 進行判空,使用 ISNULL(column) 判空,效率更高,也不會出現換行的情況。

select * from cms_subject where column is null and
column1 is not null;

select * from cms_subject where ISNULL(column) and
column1 is not null;

05、最後

2016 年 12 月份,阿里首次向業界開放了這份《Java 開發手冊》,到泰山版發佈,已經過去了 3 年多時間了,這份手冊也在全球 Java 開發者共同的努力下,成爲業界普遍遵循的開發規範。這份手冊包含的知識點非常全面,七大維度編程規約、異常日誌、單元測試、安全規約、MySQL數據庫、工程規約、設計規約都有羅列。

如果你想成爲一名優秀的 Java 工程師,那麼這份手冊上的內容幾乎是必須要掌握的。是不是已經迫不及待想要下載這份手冊了?

微信搜索「沉默王二」回覆「手冊」就可以免費獲取了,當然你也可以掃描下面的二維碼後回覆,趕緊趕緊。

最後,我衷心地祝福你,希望你能學有所成,to be better,奧利給!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章